本文分析此源码(源码作者也许叫cindy吧):http://s.yunio.com/Wd8Nxm
本项目非常值得分析的一点除了它的异步加载外,还有它良好的文件结构:
固定的临时文件夹创建放在MyApp(继承于Application)(如备注,当application/package被创建时,此函数被实例化:
1 | package cindy.android.test.synclistview; |
当然了,需要在AndroidManifest.xml中定义:
1 | ........ |
Log记录做一个类,这样即可以统一管理TAG也可以清晰的通过此类明白自己项目会涉及到问题.并且统一管理对应的显示规则:
1 | package cindy.android.test.synclistview; |
本项目封装了入口Activity的父类:
1 | package cindy.android.test.synclistview; |
通过这个统一管理了主要的一些Toast简化代码量的同时也清晰了项目会遇到的一些需要给用户提示的情况,并且定义了整体的布局。这是一个很好的方法。
由于加载是从网络上来的,需要延时是难免的。通过ProgressBar来下意识用户等候是常用方法,本项目作者将整个延时等待的load框架封装出来:
1 | package cindy.android.test.synclistview; |
这样很好的对加载框架进行控制,隐藏了方法,同时使可读性增强。
下面我们进入本项目的分析:
我们先按管理分析下作者的思路:
如果加载成功隐藏加载框架,失败显示按钮与有关文字 -> 滑动如果处于闲置状态进行加载对应范围内的图片.
首先我们看看入口Activity:
1 | package cindy.android.test.synclistview; |
继承自封装好的Activity。
创建一个adapter对象:
1 | adapter = new BookItemAdapter(this,viewBookList); |
下面我们来看下BookItemAdapter:
1 | package cindy.android.test.synclistview; |
此Adapter在构造时还获得了对应的ListView
我们可以看到
1 | mListView.setOnScrollListener(onScrollListener); |
我们看下onScrollListener:
1 | AbsListView.OnScrollListener onScrollListener = new AbsListView.OnScrollListener() { |
这里主要就是当滑动闲置的时候解锁加载.我们深入看下:
1 | package cindy.android.test.synclistview; |
可以清晰的看到只有当mAllowLoad与firstLoad同为true或者mAllowLoad与获得的position在当前界面的时候调用loadImage:
1 | private void loadImage(final String mImageUrl,final Integer mt,final OnImageLoadListener mListener){ |
这里的imageCache是一个哈希表
private HashMap<String, SoftReference> imageCache = new HashMap<String, SoftReference>();
我们可以很清晰的看到当通过图片的url地址可以在哈希表中找到直接从哈希表中得到对应的软引用(不会被随意回收,不过当内存吃紧返回00mb的时候会被回收).如果此时允许加载,调用OnImageLoadListener的onImageLoad对应的接口:
此接口在BookItemAdapter中进行了实现:
1 | SyncImageLoader.OnImageLoadListener imageLoadListener = new SyncImageLoader.OnImageLoadListener(){ |
很显然这里通过传入的position可以得到对应item的View我们可以看下BookItemAdapter中的getView
1 | convertView.setTag(position); |
确实是将对应的position设置为其tag.
回到SyncImageLoader的private void loadImage(final String mImageUrl,final Integer mt,final OnImageLoadListener mListener):
当在哈希表中找不到对应的软引用,则通过loadImageFromUrl获得:
1 | public static Drawable loadImageFromUrl(String url) throws IOException { |
此函数从网络上获得图片并创建对应Drawable.如果sd卡可用:
如果对应缓存文件存在(已经缓存),则直接从缓存文件中取得,否则从网路上读取后,创建缓存文件(同样以MD5加密形式命名)。
如果不sdcard不可用直接从网络上读取.
返回Drawable.
通过所返回的Drawable 判断是否调用onImageLoad接口或是onError接口(显示默认图片)。
在之前我们已经了解到如果SCROLL_STATE_IDLE的时候进行加载,我们看下它的调用:
1 | case AbsListView.OnScrollListener.SCROLL_STATE_IDLE: |
对应的loadImage():
1 | public void loadImage(){ |
这里的把当前界面的第一个item的position与最后一个item的position传给syncImageLoader,然后进行解锁:
1 | public void unlock(){ |
此时getView中各种加载,这里的加载条件与方法上面已经知道了。
其它的,入口的reload和刷新的作用一样.重新刷新一遍。