1. 程式人生 > >Android批量圖片載入經典系列——使用LruCache、AsyncTask快取並非同步載入圖片

Android批量圖片載入經典系列——使用LruCache、AsyncTask快取並非同步載入圖片

public class PhotoWallAdapter extends ArrayAdapter<File> implements
        OnScrollListener {

     //記錄所有正在下載或等待下載的任務。
    private Set<BitmapWorkerTask> taskCollection;
 // 圖片快取技術的核心類,用於快取所有下載好的圖片,在程式記憶體達到設定值時會//將最少最近使用的圖片移除掉。
    private LruCache<String, Bitmap> mMemoryCache;
    
//GridView的例項 private GridView mPhotoWall; //第一張可見圖片的下標 private int mFirstVisibleItem; // 一屏有多少張圖片可見 private int mVisibleItemCount; // 記錄是否剛開啟程式,用於解決進入程式不滾動螢幕,不會下載圖片的問題。 private boolean isFirstEnter = true; ArrayList<File> list = null; public PhotoWallAdapter(Context context, int
textViewResourceId, ArrayList<File> objects, GridView photoWall) { super(context, textViewResourceId, objects); mPhotoWall = photoWall; list = objects; taskCollection = new HashSet<BitmapWorkerTask>(); // 獲取應用程式最大可用記憶體 int
maxMemory = (int) Runtime.getRuntime().maxMemory(); int cacheSize = maxMemory / 8; // 設定圖片快取大小為程式最大可用記憶體的1/8 mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { return bitmap.getByteCount(); } }; mPhotoWall.setOnScrollListener(this); } public View getView(int position, View convertView, ViewGroup parent) { final File url = getItem(position); View view; if (convertView == null) { view = LayoutInflater.from(getContext()).inflate( R.layout.photo_layout, null); } else { view = convertView; } final ImageView photo = (ImageView) view.findViewById(R.id.photo); // 給ImageView設定一個Tag,保證非同步載入圖片時不會亂序 photo.setTag(url.getAbsolutePath()); setImageView(url.getAbsolutePath(), photo); return view; } /** * 給ImageView設定圖片。首先從LruCache中取出圖片的快取,設定到ImageView上。如果LruCache中沒有該圖片的快取, * 就給ImageView設定一張預設圖片。 * @param imageUrl * 圖片的URL地址,用於作為LruCache的鍵。 * @param imageView * 用於顯示圖片的控制元件。 */ private void setImageView(String imageUrl, ImageView imageView) { Bitmap bitmap = getBitmapFromMemoryCache(imageUrl); if (bitmap != null) { imageView.setImageBitmap(bitmap); } else { bitmap=getLoacalBitmap(imageUrl); imageView.setImageResource(R.drawable.empty_photo); } } /** * 將一張圖片儲存到LruCache中。 * @param key * LruCache的鍵,這裡傳入圖片的URL地址。 * @param bitmap * LruCache的鍵,這裡傳入從網路上下載的Bitmap物件。 */ @SuppressLint("NewApi") public void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (getBitmapFromMemoryCache(key) == null) { mMemoryCache.put(key, bitmap); } } /** * 從LruCache中獲取一張圖片,如果不存在就返回null。 * @param key * LruCache的鍵,這裡傳入圖片的URL地址。 * @return 對應傳入鍵的Bitmap物件,或者null。 */ @SuppressLint("NewApi") public Bitmap getBitmapFromMemoryCache(String key) { return mMemoryCache.get(key); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // 僅當GridView靜止時才去下載圖片,GridView滑動時取消所有正在下載的任務 if (scrollState == SCROLL_STATE_IDLE) { loadBitmaps(mFirstVisibleItem, mVisibleItemCount); } else { cancelAllTasks(); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { mFirstVisibleItem = firstVisibleItem; mVisibleItemCount = visibleItemCount; // 下載的任務應該由onScrollStateChanged裡呼叫,但首次進入程式時onScrollStateChanged並不會呼叫, // 因此在這裡為首次進入程式開啟下載任務。 if (isFirstEnter && visibleItemCount > 0) { loadBitmaps(firstVisibleItem, visibleItemCount); isFirstEnter = false; } } /** * 載入Bitmap物件。此方法會在LruCache中檢查所有螢幕中可見的ImageView的Bitmap物件, * 如果發現任何一個ImageView的Bitmap物件不在快取中,就會開啟非同步執行緒去下載圖片。 * * @param firstVisibleItem * 第一個可見的ImageView的下標 * @param visibleItemCount * 螢幕中總共可見的元素數 */ private void loadBitmaps(int firstVisibleItem, int visibleItemCount) { try { for (int i = firstVisibleItem; i < firstVisibleItem + visibleItemCount; i++) { String imageUrl = list.get(i).getAbsolutePath(); Bitmap bitmap = getBitmapFromMemoryCache(imageUrl); if (bitmap == null) {//如果快取沒有 BitmapWorkerTask task = new BitmapWorkerTask(); taskCollection.add(task); task.execute(imageUrl);//執行非同步任務,並傳入載入的圖片url地址(這裡是sd卡上的圖片) } else { ImageView imageView = (ImageView) mPhotoWall .findViewWithTag(imageUrl); if (imageView != null && bitmap != null) { imageView.setImageBitmap(bitmap); } } } } catch (Exception e) { e.printStackTrace(); } } /** * 取消所有正在下載或等待下載的任務。 */ public void cancelAllTasks() { if (taskCollection != null) { for (BitmapWorkerTask task : taskCollection) { task.cancel(false); } } } /** * 非同步下載圖片的任務。 */ class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> { /** * 圖片的URL地址 */ private String imageUrl; @Override protected Bitmap doInBackground(String... params) { imageUrl = params[0]; // 在後臺開始下載圖片 Bitmap bitmap = getLoacalBitmap(params[0]); if (bitmap != null) { // 圖片下載完成後快取到LrcCache中 addBitmapToMemoryCache(params[0], bitmap); } return bitmap; } @Override protected void onPostExecute(Bitmap bitmap) { super.onPostExecute(bitmap); // 根據Tag找到相應的ImageView控制元件,將下載好的圖片顯示出來。 ImageView imageView = (ImageView) mPhotoWall .findViewWithTag(imageUrl); if (imageView != null && bitmap != null) { imageView.setImageBitmap(bitmap); } taskCollection.remove(this); } } private Bitmap getLoacalBitmap(String url) { try { FileInputStream fis = new FileInputStream(url); return BitmapFactory.decodeStream(fis); // /把流轉化為Bitmap圖片 } catch (FileNotFoundException e) { e.printStackTrace(); return null; } } }

相關推薦

Android批量圖片載入經典系列——使用LruCacheAsyncTask快取並非同步載入圖片

public class PhotoWallAdapter extends ArrayAdapter<File> implements OnScrollListener { //記錄所有正在下載或等待下載的任務。 private Set<Bit

Android批量圖片載入經典系列——使用xutil框架快取非同步載入網路圖片

一、問題描述   為提高圖片載入的效率,需要對圖片的採用快取和非同步載入策略,編碼相對比較複雜,實際上有一些優秀的框架提供瞭解決方案,比如近期在git上比較活躍的xutil框架   Xutil框架提供了四大模組: 1、  DbUtil模組:採用ORM機制簡化Sqlite操作,

Android批量圖片載入經典系列——採用二級快取非同步載入網路圖片

public class AsyncImageLoader{ private MemoryCache mMemoryCache;//記憶體快取 private FileCache mFileCache;//檔案快取 private ExecutorService mExecu

Android批量圖片載入經典系列——afinal框架實現圖片的非同步快取載入

public class MoreStyleNewsListViewAdapter extends BaseAdapter { private Activity mActivity; private List<NewsItem> newsList; private

轉 UITableView 重用 UITableViewCell 並非同步載入圖片時會出現圖片錯亂的情況

UITableView 重用 UITableViewCell 並非同步載入圖片時會出現圖片錯亂的情況 當然大多數情況下可以用 SDWebImage, 這個庫功能強大,封裝的很好。但自己重頭來寫可能對問題理解的更深。 SDWebImage 有點複雜,很多人也會參考一

Android面試題(22)-lruCache與DiskLruCache快取詳解

關於lruCache(最近最少使用)的演算法,這是一個比較重要的演算法,它的應用非常廣泛,不僅僅在Android中使用,Linux系統等其他地方中也有使用;今天就來看一看這其中的奧祕;講到LruCache,就不得不講一講LinkedHashMap,而對於LinkedHashM

java對圖片的各種操作(壓縮加水印(文字或圖片旋轉)

先貼上原始碼,再呼叫測試看效果,整理了3天。如有更好想法或不同見解,歡迎@我([email protected]). import java.awt.AlphaComposite; import java.awt.Color; import java.awt.F

Android瀑布流優化,解決Recyclerview展示大批量圖片時Item自動切換閃爍空白等問題

本文涉及的程式碼案例可以在下方的連結中找到,如果對你有幫助,請給個Star(#^.^#)問題分析        這段時間業務需求用到RecyclerView瀑布流載入並展示大批量圖片,但一開始單純使用RecyclerView直接載入圖片,使得顯示上出現了滑動到頂端時閃爍,It

Android瀑布流優化,解決Recyclerview展示大批量圖片時Item自動切換閃爍空白等問題...

code小生,一個專注於 Android 領域的技術分享平臺作者:請抱抱陳先生地址:https:

Android Glide載入圖片時轉換為圓形圓角毛玻璃等圖片效果

Android Glide載入圖片時轉換為圓形、圓角、毛玻璃等圖片效果 附錄1簡單介紹了Android開源的圖片載入框架。在實際的開發中,雖然Glide解決了快速載入圖片的問題,但還有一個問題懸而未決:比如使用者的頭像,往往使用者的頭像是從伺服器端讀出的一個普通矩形圖片

Android經典面試問題:請你設計一套圖片非同步載入快取方案——圖片的三級快取

友情提示:文章最後附有專案原始碼現在,Android有很多優秀的圖片載入框架。例如:Picasso,Glide,Fresco。我們幾乎只要簡單呼叫幾句程式碼就可以很好的實現圖片的載入。很多時候也不需要我們親自去寫圖片載入方案。但是,學習圖片的三級快取策略無論是在面試時,還是對

Androidandroid的框架區別(網路框架圖片非同步載入快取框架資料框架)特點整理

在我們安卓開發中,很多繁瑣的程式碼會很頭疼,編寫程式的週期會增加,因此很多框架都冒出來了,我們在搞懂底層原理之時,我們更應該學會用一些優秀框架來解決複雜程式碼,和繁瑣的重寫程式碼。因為針對最簡單的case,我只需要提供request url,成功時的callba

Android Universal-Image-Loader,Volley,PicassoFresco和Glide五大Android開源元件載入網路圖片的優缺點比較

關於 Fresco Facebook最近推出了一款用於Android應用中展示圖片的強大圖片庫Fresco,它能夠從網路、本地儲存和本地資源中載入圖片。而且,為了節省資料和CPU,它擁有三級快取。 Fresco 是一個強大的圖片載入元件。 Fresco 中設計有一個叫做 image pipeline

Android使用LruCacheDiskLruCache實現圖片快取+圖片瀑布流

PPS:本文僅用於學習利用LruCache、DiskLruCache圖片快取策略、實現瀑布流和Matix檢視大圖縮放移動等功能,如果想用到專案中,建議用更成熟的框架,如glide、picasso 等。 先上效果圖: ###圖片瀑布流 這個用

spring MVC載入靜態資源(js圖片css等)

這裡介紹三種在spring mvc框架中,載入靜態資源的方式: 如果在web.xml中配置了以下攔截,載入不了靜態資源的問題: <!-- 對映所有的請求 -->     <servlet-mapping>  &nb

mybatis基礎系列(四)——關聯查詢延遲載入一級快取與二級快取

關本文是Mybatis基礎系列的第四篇文章,點選下面連結可以檢視前面的文章: mybatis基礎系列(三)——動態sql mybatis基礎系列(二)——基礎語法、別名、輸入對映、輸出對映 mybatis基礎系列(一)——mybatis入門 關聯查詢 在進行表設計時,往往需要在具體的業務基礎上分析表與表之間的

MybatisDay02(批量generator二級快取延遲載入

mybatis 高階對映 查詢快取 spring集合 mybatis是什麼? mbatis是一個持久層框架,mybatis是一個不完全的ORM框架,sql語句需要程式設計師自己去編寫,但是mybatis有對映(輸入引數對映、輸出結果對映) mybatis入門門檻不高,學習成本低,讓

Android 技能圖譜學習路線系列-Java基礎之方法鎖物件鎖類鎖

先了解一下Synchronized的用法。 一、Synchronized的用法 在修飾程式碼塊的時候需要一個reference物件作為鎖的物件。 在修飾方法的時候預設是當前物件作為鎖的物件。 在修飾類時候預設是當前類的Class物件作為鎖的物件。 二、三種鎖得區

Android:將一個Activity某塊佈局轉換成圖片

使用截圖,然後儲存圖片 如果要儲存的佈局正好是撐滿這個螢幕,那可以使用截圖的方式來儲存圖片; 如果只是螢幕的某一個部分,那才用截圖後,還得對截圖後的圖片進行二次裁剪,而且要裁剪的座標點也比較難正確得出; 要儲存的佈局大於當前螢幕,那就得多次截

Android TextView使用HTML處理字型樣式顯示圖片

         學Android的時候突然想到一個問題:怎麼用TextView控制元件顯示帶有格式的文字,可否使用Html佈局?查了下Android 幫助文件,其提供了android.text.Html類和Html.ImageGetter、Html.TagHandler介