【從零開始寫一個簡單的ImageLoader框架】ImageLoader分析
#相關文章
【從零開始寫一個簡單的ImageLoader框架】專案介紹
【從零開始寫一個簡單的ImageLoader框架】ImageLoader分析
【從零開始寫一個簡單的ImageLoader框架】MyImageLoader程式碼簡介
#專案涉及知識點
##1、網路獲取
##2、圖片壓縮
##3、記憶體快取
##4、磁碟快取
##5、執行緒池
##6、Handler
##7、RecyclerView(demo中使用)
#ImageLoader獲取圖片一般流程
1、從記憶體快取中檢視是否有該圖片,如果有就設定到imageView上。
2、如果沒有記憶體快取,就從磁碟快取中檢視是否有該圖片,如果有就設定到imageView上,並且把該圖片設定到記憶體快取中。
3、如果既沒有記憶體快取也沒有磁碟快取,那麼就直接從網路獲取該圖片,並使用磁碟快取,然後從磁碟中讀取該圖片。將圖片根據ImageView的寬高壓縮後進行顯示。
4、由於獲取記憶體快取較快,所以不需要使用執行緒。
而磁碟快取由於存在從網路下載圖片這一較為耗時的環節,所以要使用執行緒。
考慮到可能會有多個圖片同時顯示,所以就要使用執行緒池進行統一管理。
5、線上程中無法直接更新UI,所以也要使用到Handler。
#從程式碼瞭解流程(建議結合原始碼看)
##程式碼預覽
在筆者demo中主要使用到的方法為bindBitMap,此方法使用與ImageRecyclerAdapter中
public void setData(String url) {
//垂直線性佈局
//載入高清圖片並按寬高壓縮
//MyUtils.Log(url);
MyImageLoader.getInstance(context).bindBitmap(url, imageView, width, height);
}
我們直接跳轉到bindBitmap中看邏輯:
public void bindBitmap(final String uri, final ImageView imageView, final int reqWidth, final int reqHeight) {
//設定載入loadding圖片
imageView.setImageResource(R.drawable.ic_loading);
//從記憶體快取中獲取bitmap
Bitmap bitmap = imageLrucache.loadBitmapFromMemCache(uri);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
return;
}
//磁碟快取包含在LoadBitmapTask中
LoadBitmapTask loadBitmapTask = new LoadBitmapTask(mContext, imageView, uri, reqWidth, reqHeight);
//使用執行緒池去執行Runnable物件
THREAD_POOL_EXECUTOR.execute(loadBitmapTask);
}
可以看到,如果記憶體快取讀到了bitmap,那麼就會直接顯示並且退出,如果沒有,那麼就會執行LoadBitmapTask,LoadBitmapTask是一個Runnable物件,使用執行緒池呼叫時,它的邏輯會是線上程中進行的,我們可以繼續看一下里面的邏輯。
@Override
public void run() {
//從磁碟或者網路獲取bitmap
final Bitmap bitmap = loadBitmap(uri, reqWidth, reqHeight);
//使用handler更新UI
TaskResult loaderResult = new TaskResult(imageView, bitmap);
imageHandler.obtainMessage(MESSAGE_POST_RESULT, loaderResult).sendToTarget();
if (callback != null) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
callback.onResponse(bitmap);
}
});
}
}
我們發現loadBitmap(uri, reqWidth, reqHeight)在之後,就直接使用Handler進行UI的操作了,那麼執行緒邏輯必然在這個裡面。
private Bitmap loadBitmap(String uri, int reqWidth, int reqHeight) {
Bitmap bitmap = null;
try {
//從磁碟快取中獲取bitmap
bitmap = MyImageLoader.getImageDiskLruCache(mContext).loadBitmapFromDiskCache(uri, reqWidth, reqHeight);
if (bitmap != null) {
MyUtils.Log("從磁碟快取中獲取到了bitmap");
//新增到記憶體快取中
MyImageLoader.getImageLruCache().put(MD5Utils.hashKeyFromUrl(uri), bitmap);
return bitmap;
} else {
//從網路下載bitmap到磁碟快取,並從磁碟快取中獲取bitmap
bitmap = loadBitmapFromHttp(uri, reqWidth, reqHeight);
if (bitmap != null) {
MyUtils.Log("從網路下載並儲存到磁碟並從中讀取bitmap成功");
}
}
} catch (IOException e) {
e.printStackTrace();
}
if (bitmap == null && !mIsDiskLruCacheCreated) {
//如果sd卡已滿,無法使用磁碟快取,則通過網路下載bitmap,一般不會呼叫這一步
bitmap = NetWork.downloadBitmapFromUrl(uri);
MyUtils.Log("sd卡滿了,直接從網路獲取");
}
return bitmap;
}
如上,我們就找到了磁碟快取的程式碼了:從磁碟快取中如果找到了圖片,就會將圖片新增到記憶體快取中並返回bitmap,如果沒有找到,就會從網上進行下載。
#知識點詳述連結
以下知識點於《Android開發藝術探索》中均有闡述。
##1、圖片壓縮
此文章來自 中文版的Android Training。
http://hukai.me/android-training-course-in-chinese/graphics/displaying-bitmaps/load-bitmap.html
##2、記憶體快取
此文章來自 中文版的Android Training。
http://hukai.me/android-training-course-in-chinese/graphics/displaying-bitmaps/cache-bitmap.html
##3、磁碟快取
Android DiskLruCache完全解析,硬碟快取的最佳方案
此文章為郭霖前輩所著。
http://blog.csdn.net/guolin_blog/article/details/28863651
##4、執行緒池
此文章來自 中文版的Android Training。
http://hukai.me/android-training-course-in-chinese/performance/multi-threads/create-threadpool.html
##5、Handler
Handler類和Handler,Loop,MessageQueue的工作原理
http://blog.csdn.net/double2hao/article/details/50991441
##7、RecyclerView(demo中使用)
android RecyclerView佈局真的只是那麼簡單!(筆者原創)
http://blog.csdn.net/double2hao/article/details/51177594
#專案下載地址
相關文章
- 【從零開始寫一個簡單的ImageLoader框架】專案介紹框架
- 【從零開始寫一個簡單的ImageLoader框架】MyImageLoader程式碼簡介框架
- 從零開始寫JavaScript框架(一)JavaScript框架
- ImageLoader的優化寫法優化
- Android開源框架ImageLoader的完美例子Android框架
- 從零開始寫一個微前端框架-沙箱篇前端框架
- 從零開始寫一個ExporterExport
- 用 Python 從零開始寫一個簡單的直譯器(3)Python
- 用 Python 從零開始寫一個簡單的直譯器(4)Python
- 用 Python 從零開始寫一個簡單的直譯器(2)Python
- 從零開始編寫自己的JavaScript框架(一)JavaScript框架
- 從零開始手寫一個微前端框架-渲染篇前端框架
- 從零開始實現一個簡易的Java MVC框架JavaMVC框架
- 從零開始仿寫一個抖音App——開始APP
- 從零開始寫JavaScript框架(二)JavaScript框架
- 從零開始寫一個網頁網頁
- 如何從零開始學習一個框架框架
- 從零開始實現一個RPC框架(零)RPC框架
- 如何從零開始寫一個網站網站
- 從零開始寫一個微前端框架-樣式隔離篇前端框架
- 從零開始寫一個微前端框架-資料通訊篇前端框架
- 從零開始編寫一個 Python 非同步 ASGI WEB 框架Python非同步Web框架
- 從零開始寫一個node爬蟲(一)爬蟲
- Android ImageLoader框架之基本架構Android框架架構
- 0-開發框架Codea簡介-從零開始寫一個武俠冒險遊戲框架遊戲
- 從零開始編寫自己的JavaScript框架(二)JavaScript框架
- 從零開始實現一個RPC框架(一)RPC框架
- 從零構建一個簡單的 Python 框架Python框架
- 從零開始編寫一個babel外掛Babel
- 從零開始寫一個Javascript解析器JavaScript
- 從零開始:用REACT寫一個格鬥遊戲(一)React遊戲
- 【Android】開源專案UniversalImageLoader及開源框架ImageLoaderAndroid框架
- 從零開始手寫Koa2框架框架
- Android ImageLoader 框架之圖片快取Android框架快取
- 從零開始實現一個RPC框架(五)RPC框架
- 從零開始實現一個RPC框架(四)RPC框架
- 從零開始實現一個RPC框架(三)RPC框架
- 從零開始實現一個RPC框架(二)RPC框架