Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [Android]ListView的Adapter.getView()方法中延遲加載圖片的優化

[Android]ListView的Adapter.getView()方法中延遲加載圖片的優化

編輯:關於Android編程

舉個例子吧,以好友列表為例   ListView中每個Item表示一個好友,每個好友中都有一個頭像,需要從服務端加載到本地,然後顯示在item中。   顯然,啟動加載圖片的過程應該是在getView()方法中觸發,啟動一個線程,然後下載頭像圖片。這裡使用我寫的一個開源框架ImageLoaderSample(https://github.com/wangjiegulu/ImageLoaderSample)來加載圖片,並實現內存緩存和本地緩存。   額--這裡不再介紹ImageLoaderSample的用法了,給個傳送門:http://www.cnblogs.com/tiantianbyconan/p/3574131.html       再來看看getView()方法的調用時機:   1. Adapter調用NotifyDataChanged的時候   2. ListView滾動時,也就是convertView不斷復用的時候。   也就是說,每當ListView滾動時,getView()方法不斷被調用,圖片下載的過程不斷地執行(當然,ImageLoaderSample中會有緩存,但是內存緩存時有限的,如果內存緩存中找不到要顯示的圖片,那就需要到文件緩存中查找,需要進行io讀寫,這個也是相對比較耗時的),顯然,這裡面還有優化的余地。   怎麼去優化這裡?只要讓ListView滾動的時候圖片顯示的時候不要去進行io讀寫就好了,具體邏輯如下:   -如果調用GetView方法時,ListView處於停止狀態,則先去內存中查找頭像圖片;如果內存圖片存在,則顯示內存中保存好的圖片;如果內存圖片不存在,則繼續到文件緩存中找,如果文件緩存圖片存在,則顯示文件緩存中的圖片;如果文件緩存圖片不存在,則根據url去網絡下載這張圖片,然後顯示;   -如果調用getView方法時,ListView處於滾動狀態,則去內存中查找頭像的圖片;如果內存圖片存在,則顯示內存中保存好的圖片;如果內存圖片不存在,則顯示一張默認的圖片(省去了從文件緩存中找圖片和網絡中去請求圖片的步驟)。       這樣的話,我們就必須要改寫BaseAdapter,讓它能夠監測ListView的滾動狀態,並在Adapter中可以獲取到當前ListView的滾動狀態。所以改造BaseAdapter,ABaseAdapter(https://github.com/wangjiegulu/AndroidBucket/blob/master/src/com/wangjie/androidbucket/adapter/ABaseAdapter.java):   復制代碼  1 package com.wangjie.androidbucket.adapter;  2   3 import android.widget.*;  4 import com.wangjie.androidbucket.adapter.listener.OnAdapterScrollListener;  5   6 /**  7  * Author: wangjie  8  * Email: [email protected]  9  * Date: 12/3/14. 10  */ 11 public abstract class ABaseAdapter extends BaseAdapter implements AbsListView.OnScrollListener { 12     private OnAdapterScrollListener onAdapterScrollListener; 13     /** 14      * 當前listview是否屬於滾動狀態 15      */ 16     private boolean isScrolling; 17  18     public boolean isScrolling() { 19         return isScrolling; 20     } 21  22     public void setOnAdapterScrollListener(OnAdapterScrollListener onAdapterScrollListener) { 23         this.onAdapterScrollListener = onAdapterScrollListener; 24     } 25  26     protected ABaseAdapter(AbsListView listView) { 27         listView.setOnScrollListener(this); 28     } 29  30     @Override 31     public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 32         if (null != onAdapterScrollListener) { 33             onAdapterScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); 34         } 35     } 36  37     @Override 38     public void onScrollStateChanged(AbsListView view, int scrollState) { 39         if (null != onAdapterScrollListener) { 40             onAdapterScrollListener.onScrollStateChanged(view, scrollState); 41         } 42  43         // 設置是否滾動的狀態 44         if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) { // 不滾動狀態 45             isScrolling = false; 46             this.notifyDataSetChanged(); 47         } else { 48             isScrolling = true; 49         } 50     } 51 } 復制代碼 如上述代碼所示,該Adapter實現了AbsListView.OnScrollListener,並在構造方法中給ListView綁定了OnScrollListener,在實現的onScrollStateChanged方法中獲取到當前滾動狀態,並且保存這個狀態isScrolling,並暴露isScrolling()方法給外面。   OnAdapterScrollListener這個接口是繼承了AbsListView.OnScrollListener,因為這裡在Adapter中一景設置了OnScrollListener了,所以如果在外面設置了新的OnScrollListener的話,就會失效了,所以必須提供另外一個setOnAdapterScrollListener,然後再傳入一個OnScrollListener,然後在每個方法中進行回調就好了,因為考慮到以後可能會擴展其他的接口方法,所以這裡新寫了一個接口(為了以後擴展時原來的代碼不會被影響,推薦使用OnAdapterScrollSampleListener這個實現類來代替OnAdapterScrollListener這個接口,OnAdapterScrollSampleListener這個類只是對OnAdapterScrollListener的所有方法進行了空實現)。       然後我們編寫一個MyAdapter繼承ABaseAdapter,然後,在getView()方法中,需要顯示頭像的時候調用如下方法:   // 如果在滾動(從內存中查找,找不到也不進行網絡請求)   ImageLoader.getInstances().displayImage(headUrl, headIv, null, R.drawable.default_head, isScrolling()); 看到木有?
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved