作者:lb377463323
出处:http://blog.csdn.net/lb377463323
原文链接:http://blog.csdn.net/lb377463323/article/details/70890461
转载请注明出处!
在Android 7.0 Gallery图库源码分析3 – 数据加载及显示流程一文最后讲了AlbumSetSlidingWindow的onContentChanged方法,专辑缩略图和缩略图下面的label的加载就是在此方法中完成的
public void onContentChanged(int index) {
//mData是容量为96的AlbumSetEntry数组,index是代表加载哪一个专辑,范围是0-(n-1),n为专辑数
AlbumSetEntry entry = mData[index % mData.length];
//专辑缩略图和label主要由下面三个方法完成
updateAlbumSetEntry(entry, index);
updateAllImageRequests();
updateTextureUploadQueue();
//onContentChanged方法就是执行mSlotView.invalidate()刷新界面
if (mListener != null && isActiveSlot(index)) {
mListener.onContentChanged();
}
}
首先分析updateAlbumSetEntry(entry, index)方法
private void updateAlbumSetEntry(AlbumSetEntry entry, int slotIndex) {
......
//cover是从专辑里面获取的一个图片,用来作为专辑缩略图
MediaItem cover = mSource.getCoverItem(slotIndex);
if (album != null) {
//AlbumLabelLoader就是用来加载缩略图下面的label,如专辑名、此专辑有多少张图片等,看参数也能知道
entry.labelLoader = new AlbumLabelLoader(
slotIndex, title, totalCount, sourceType);
}
if (cover != null) {
//AlbumCoverLoader是用来加载专辑缩略图的加载器
entry.coverLoader = new AlbumCoverLoader(slotIndex, cover);
}
}
现在加载器都已准备好,下面看加载器是如何加载图片的,回到onContentChanged方法,看下updateAllImageRequests()方法
private void updateAllImageRequests() {
mActiveRequestCount = 0;
for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {
AlbumSetEntry entry = mData[i % mData.length];
//下面两句开始执行图片加载
if (startLoadBitmap(entry.coverLoader)) ++mActiveRequestCount;
if (startLoadBitmap(entry.labelLoader)) ++mActiveRequestCount;
}
......
}
根据下述代码,发现图片加载最终还是执行Loader的submitBitmapTask()方法
private static boolean startLoadBitmap(BitmapLoader loader) {
loader.startLoad();
return loader.isRequestInProgress();
}
public synchronized void startLoad() {
if (mState == STATE_INIT) {
mState = STATE_REQUESTED;
if (mTask == null) mTask = submitBitmapTask(this);
}
}
本文只分析专辑缩略图的加载,至于缩略图下面的label请自行查看代码,原理都是一样的。
下面分析AlbumCoverLoader的submitBitmapTask方法
protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) {
//mMediaItem为LocalImage或LocalVideo,下面只分析LocalImage
return mThreadPool.submit(mMediaItem.requestImage(
MediaItem.TYPE_MICROTHUMBNAIL), l);
}
根据上述代码可知,缩略图加载是通过线程池来完成的。至于此处线程池的原理,submit之后会在线程池中执行任务加载缩略图,从ThreadPool的run()方法中知道完成缩略图加载任务后,会调用mListener.onFutureDone(this),这里mListener就是BitmapLoader自身,从future.get中得到Bitmap传给onLoadComplete(mBitmap)。 之后发送Handler消息MSG_UPDATE_ALBUM_ENTRY调用AlbumCoverLoader的updateEntry()。
下面分析缩略图是如何加载的,看下LocalImage的代码
//requestImage返回加载Bitmap的Job工作任务,也就是ImageCacheRequest类
public Job<Bitmap> requestImage(int type) {
return new LocalImageRequest(mApplication, mPath, dateModifiedInSec,
type, filePath);
}
public static class LocalImageRequest extends ImageCacheRequest {
private String mLocalFilePath;
LocalImageRequest(GalleryApp application, Path path, long timeModified,
int type, String localFilePath) {
super(application, path, timeModified, type,
MediaItem.getTargetSize(type));
mLocalFilePath = localFilePath;
}
}
之后线程池会执行此ImageCacheRequest的run方法,完成图像数据的编解码生成一个Bitmap,这就是所需要的专辑缩略图。至于如何编解码的,可以查看ImageCacheRequest的run方法,因为太过复杂,本文就暂时不细讲了,后续有时间再讲解。
还有一点,这里只是加载Bitmap,要想将Bitmap显示到界面上还需要通过AlbumSetSlotRenderer的renderSlot方法来实现。