您的位置:首页 > 产品设计 > UI/UE

开源项目分析之UIL(续)

2015-09-09 10:36 459 查看


先直接上流程图

在上一篇我们大概的浏览了一下图片是怎样网络到本地,然后显示出来的。这一讲我们要分析一些细节问题。

图片的处理思路

该开源项目的处理也是符合真实世界的思路的,有几个问题我们需要理清楚

1.我们拥有什么 图片的url和ImageView

2.我们希望怎样处理图片 从网络上解析bitmap,缓存到磁盘,缓存到本地,显示出来

那么,我就分几个模块分析一下

下载图片

我们之前通过分析指导,下载图片是由一个Runnable来完成的,这是一个异步操作。

LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo,
defineHandler(options));


我们通过ImageLoaderEngine来执行这个任务,他内部封装了一个Executor,实际是通过开启子线程来执行这个任务。那么最后的执行实体还是在run方法里面。那么既然我已经开启了一个加载任务,其实是因为之前我们在磁盘和内存缓存中并没有找到。那么我加载到后,就要先缓存在磁盘,内存,然后再开启一个显示图片的任务,当然,此时我们已经得到bitmap了。这里的ImageDownLoader是专门用于从网络去下载图片的,但是呢,他并不是将拿到的输入流直接解析为bitmap,而是将流保存在本地,如果用户选择了缓存到磁盘,那么他将该流缓存在磁盘,并对磁盘中的流进行解析,得到bitmap.这边还有一个解析器,是专门将bitmap流解析为bitmap的,如果你选择了缓存到磁盘,那么我们解析磁盘中的流,否则,直接解析uri,即网络流。反正最后我们得到的肯定是一个bitmap。请注意,这上面的一切都是在子线程中做的。仔细看下图,我们可以发现PreProcessor和PostProcess,前者是拿到bitmap后,缓存到内存之前所做的处理,后者是从缓存中拿出后,准备显示到ImageView上时需要做的处理。后面接着就是开启一个显示的任务。

DisplayBitmapTask displayBitmapTask = new DisplayBitmapTask(bmp, imageLoadingInfo, engine, loadedFrom);
runTask(displayBitmapTask, syncLoading, handler, engine);


我们知道,显示图片必须在UI线程完成,那么,他是怎么保证的呢?我们可以看到有defineHandler这个方法

private static Handler defineHandler(DisplayImageOptions options) {
Handler handler = options.getHandler();
if (options.isSyncLoading()) {
handler = null;
} else if (handler == null && Looper.myLooper() == Looper.getMainLooper()) {
handler = new Handler();
}
return handler;
}


他必须确保Handler是和主轮询器绑定的,也就是在主线程中。

磁盘缓存

这里面他默认用的是LruDiskCache,那么我们就一起来看一看他是怎么缓存的,又是怎么取出的呢?

这其实是一个自己封装的类,其实质还是用的总所周知的DiskLruCache.毕竟为了实现一些特殊的需求,LruDiskCache需要更多的参数。

LruDiskCache(individualCacheDir,reserveCacheDir,diskCacheFileNameGenerator, diskCacheSize,diskCacheFileCount)


第一个参数 是我们要缓存的目录,第二个是备用的,第三个是名字产生器,就是根据uri来产生一个缓存的文件的名字。

1.怎么保存的呢?

save 好吧,必须要分析一下DiskLruCache的内部类Editor了。它里面有个成员变量written

private Editor(Entry entry) {
this.entry = entry;
this.written = (entry.readable) ? null : new boolean[valueCount];
}


看看他是怎么初始化的,这个valueCount表示的是你的缓存文件要保存的数量。那么他又是怎么实现

一个key值对应多个缓存文件的呢? 他的文件的命名如下:

public File getDirtyFile(int i) {
return new File(directory, key + "." + i + ".tmp");
}


当我们调用save的时候,我们就将输出流和该文件绑定起来了。这里面还有些什么dirtyFile和cleanFile的

处理,就不一一详述了。

本地缓存

LruMemoryCache

显示

BitMapDisplayer 反正最后走到了ViewAware里面,进行了一个判断

if (Looper.myLooper() == Looper.getMainLooper()) {


先说到这吧,最重要的是把我思路,整个流程到底是怎么走的,然后再分析一些细节的处理,如果有特殊需求

可以灵活的更改逻辑。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  开源项目