Android面试相关程序员Android知识

从零开始撸一个Fresco之硬盘缓存

2017-03-25  本文已影响1491人  何时夕

转载请注明出处
Fresco源代码文档翻译项目请看这里:Fresco源代码文档翻译项目
硬盘缓存是android图片框架中比较重要的一个模块,Fresco中自己重写了一个硬盘缓存框架,代替了android本身的DiskLruCache,所以今天我们就来介绍Fresco中的硬盘缓存,并且将其提取出来成为我们自己的框架。我已经成功提取出了 Fresco 中的硬盘缓存框架,这是项目地址Frsco硬盘缓存框架项目地址,建议大家在看文章的时候结合项目代码,项目中的每个class文件中都有注释,看起来还是比较容易的。

一、目录介绍

二、硬盘缓存核心类分析

先上一张图,让大家简单了解各个接口提供的api。


核心类关系图

1.DefaultDiskStorage

这个class的代码就不贴了,强烈建议读者把我前面的项目下载下来,结合博客一起观看。

这个类是DiskStorage接口的实现类,前面说了这个类是直接与android的文件系统打交道的类。这个类有以下几个功能特点:

2.DiskStorageCache

同样不贴代码,再次建议大家下载项目代码观看博客。

这个类是FileCache的实现类,其通过DefaultDiskStorage与android文件系统打交道,并且处理文件缓存的各种逻辑。来说说它的功能特点:

三、Fresco硬盘缓存框架的使用

Fresco在使用硬盘缓存框架的时候,与其他模块通信的时候使用了两个类DiskCacheConfig和DiskStorageCache。DiskCacheConfig很好理解,负责用Builder模式创建一个DiskStorageCache。所以这里归更到底就是使用DiskStorageCache暴露出来的增删改查等api,而硬盘缓存框架中的其他类与Fresco的其他模块是解耦的,这也是软件工程中的一个重要的思想。所以接下来我们就来使用一下DiskStorageCache,也算是对这篇博客的总结。

这里代码不多所以贴下代码:

public class MainActivity extends AppCompatActivity {
FileCache mFileCache;
Button buttonInsert;
Button buttonHasKey;
Button buttonRemove;
Button buttonClearAll;
Button buttonGetCache;
ImageView imageView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    initDiskCache();
    initView();

    final int[] times = {0};
    buttonInsert.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            SimpleCacheKey simpleCacheKey=new SimpleCacheKey(String.valueOf(times[0]));
            times[0]++;
            insert(simpleCacheKey);
        }
    });

    buttonHasKey.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(MainActivity.this, "key 5 是否存在?" + mFileCache.hasKey(new SimpleCacheKey("5")), Toast.LENGTH_SHORT).show();
        }
    });

    buttonRemove.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            times[0]--;
            SimpleCacheKey simpleCacheKey=new SimpleCacheKey(String.valueOf(times[0]));
            mFileCache.remove(simpleCacheKey);
        }
    });

    buttonClearAll.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mFileCache.clearAll();
            times[0]=0;
        }
    });

    buttonGetCache.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            getCache();
        }
    });
}

private void initDiskCache(){

    DiskCacheConfig diskCacheConfig=DiskCacheConfig.newBuilder(this).build();
    Toast.makeText(this, "缓存文件夹:"+diskCacheConfig.getBaseDirectoryPathSupplier().get().getPath(), Toast.LENGTH_SHORT).show();
    DefaultDiskStorage defaultDiskStorage=new DefaultDiskStorage(
            diskCacheConfig.getBaseDirectoryPathSupplier().get(),
            diskCacheConfig.getVersion(),
            diskCacheConfig.getCacheErrorLogger());

    DiskStorageCache.Params params = new DiskStorageCache.Params(
            diskCacheConfig.getMinimumSizeLimit(),
            diskCacheConfig.getLowDiskSpaceSizeLimit(),
            diskCacheConfig.getDefaultSizeLimit());


    CacheEventListener cacheEventListener=new CacheEventListener() {
        @Override
        public void onHit(CacheEvent cacheEvent) throws IOException {
            Log.d("MainActivity Cache hit", cacheEvent.getCacheKey().getUriString());
            Log.d("MainActivity", "mFileCache.getDumpInfo():" + mFileCache.getDumpInfo());
        }

        @Override
        public void onMiss(CacheEvent cacheEvent) throws IOException {
            Log.d("MainActivity Cache miss", cacheEvent.getCacheKey().getUriString());
            Log.d("MainActivity", "mFileCache.getDumpInfo():" + mFileCache.getDumpInfo());
        }

        @Override
        public void onWriteAttempt(CacheEvent cacheEvent) throws IOException {
            Log.d("MainActivity Cache write start", cacheEvent.getCacheKey().getUriString());
            Log.d("MainActivity", "mFileCache.getDumpInfo():" + mFileCache.getDumpInfo());
        }

        @Override
        public void onWriteSuccess(CacheEvent cacheEvent) throws IOException {
            Log.d("MainActivity Cache write success", cacheEvent.getCacheKey().getUriString());
            Log.d("MainActivity", "mFileCache.getDumpInfo():" + mFileCache.getDumpInfo());
        }

        @Override
        public void onReadException(CacheEvent cacheEvent) {
            Log.d("MainActivity Cache ReadException", cacheEvent.getCacheKey().getUriString());
        }

        @Override
        public void onWriteException(CacheEvent cacheEvent) {
            Log.d("MainActivity Cache WriteException", cacheEvent.getCacheKey().getUriString());
        }

        @Override
        public void onEviction(CacheEvent cacheEvent) throws IOException {
            Log.d("MainActivity Cache Eviction", cacheEvent.getCacheKey().getUriString());
            Log.d("MainActivity", "mFileCache.getDumpInfo():" + mFileCache.getDumpInfo());
        }

        @Override
        public void onCleared() throws IOException {
            Log.d("MainActivity", "Cleared");
            Log.d("MainActivity", "mFileCache.getDumpInfo():" + mFileCache.getDumpInfo());
        }
    };

    mFileCache=new DiskStorageCache(
            defaultDiskStorage,
            diskCacheConfig.getEntryEvictionComparatorSupplier(),
            params,
            cacheEventListener,
            diskCacheConfig.getCacheErrorLogger(),
            diskCacheConfig.getDiskTrimmableRegistry(),
            diskCacheConfig.getContext(),
            Executors.newSingleThreadExecutor(),
            diskCacheConfig.getIndexPopulateAtStartupEnabled());

}

private void initView(){
    buttonInsert=(Button)findViewById(R.id.insert);
    buttonHasKey=(Button)findViewById(R.id.hasKey);
    buttonRemove=(Button)findViewById(R.id.remove);
    buttonClearAll=(Button)findViewById(R.id.clearAll);
    buttonGetCache=(Button)findViewById(R.id.getCache);
    imageView=(ImageView)findViewById(R.id.image);
}

private void insert(SimpleCacheKey simpleCacheKey){
    try {
        mFileCache.insert(simpleCacheKey, new WriterCallback() {
            @Override
            public void write(OutputStream os) throws IOException {
                FileUtils.bitmapToFile(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher),os);
            }
        });
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void getCache(){
    BinaryResource diskCacheResource = mFileCache.getResource(new SimpleCacheKey("2"));
    if (diskCacheResource==null) Toast.makeText(this, "miss 2", Toast.LENGTH_SHORT).show();
    else {
        Toast.makeText(this, "hit 2", Toast.LENGTH_SHORT).show();
        try {
            imageView.setImageBitmap(BitmapFactory.decodeStream(diskCacheResource.openStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
}

以上就是Fresco硬盘缓存框架的使用。

四、总结

Fresco的硬盘缓存框架,还是挺有趣的,其中用到了许多软件工程的思想与Java设计模式。Fresco中还有许多模块非常有趣,做个预告下一篇博客将会分析Fresco的内存缓存框架有兴趣的同学一定别错过了。

上一篇 下一篇

猜你喜欢

热点阅读