編輯:關於android開發
主要分析Android中Listview滾動過程造成的圖片顯示重復、錯亂、閃爍的原因及解決方法,順便跟進Listview的緩存機制。
1、原因分析 Listview item 緩存機制:為了使得性能更優,Listview會緩存行item(某行對應的view)。listview通過adapter的getview函數獲得每行的item。滑動過程中, a、如果某行item已經劃出屏幕,若該item不在緩存內,則put進緩存,否則更新緩存; b、獲取滑入屏幕的行item之前會先判斷緩存中是否有可用的item,如果有,作為convertview參數傳遞給adapter的getview。 這樣的話如下的getview寫法就可以充分利用緩存大大提升listview的性能。即便上萬個行item,最多inflate的次數為n,n為一屏最多顯示listview行item的個數。 @Override public View getView(int position,View convertView,ViewGroup parent){ ViewHolder holder; if(convertView == null){ convertView = inflater.inflate(R.layout.list_item,null); holder = new ViewHolder(); ....convertView.setTag(holder); }else{ holder = (ViewHolder)convertView.getTag(); } } 這樣提升了性能,但同時造成了一些問題。 本文原創:http://blog.sina.com.cn/s/blog_b15639e00101sgru.html a、行item圖片顯示重復 這個顯示重復是指當前行item顯示了之前某行item的圖片 比如listview滑動到第二行會異步加載某個圖片,但是加載很慢,加載過程中listview已經加載到15行,且滑動過程中該圖片加載結束,第二行 已經不再屏幕內,根據上面介紹的緩存原理,第二行的view可能被第14行服用,這樣我們看到的就是14行顯示了本該屬於第二行的圖片,造成重復。 b、行item圖片顯示錯亂 這個顯示錯亂是指某行item顯示了不屬於該行item的圖片。 比如listview滑動到第二行會異步加載某個圖片,但是加載很慢,加載過程中listview已經滑動到14行,第二行已經不再屏幕內,根據上面介紹 的緩存原理,第二行的view可能被第14行的復用,第十四行顯示了第二行的view這時之前的圖片加載結束,就會顯示在第14行,造成混亂。 c、行item圖品顯示閃爍 上面b情況,14行圖片又很快加載結束,所以我們看到第14行先顯示了第二行的圖片,馬上又顯示了自己的圖片進行覆蓋造成的閃爍錯亂。 2、解決方法 通過上面的分析我們知道了出現錯亂的原因是異步加載及對象被復用造成的,如果每次getview能給對象一個標識,在異步加載完成時比較標識與當前的item的標識是否是一致的,一致的則顯示,否則不做處理即可。 代碼中加上 @Override public View getView(int position,View convertView,ViewGroup parent){ ViewHolder holder; if(convertView == null){ convertView = inflater.inflate(R.layout.list_item,null); holder = new ViewHolder(); ....convertView.setTag(holder); }else{ holder = (ViewHolder)convertView.getTag(); } 。。。。。 imageview.setTag(imageurl); if(!cache.icon_catch.get(imageurl,imageview){ imageview.setimageDrawable(null); } }其中setTag表示設置標識,方便下面進行標志比對
1 if ( ! Cache . ICON_CACHE . get ( imageUrl , imageView ) )Cache.ICON_CACHE為ImageCache的實例,表示如果不在緩存內則設置drawable為null(當然你可以可以設置為你自己的默認資源),防止顯示了之前某個行item的圖片,解決了a. 行item圖片顯示重復問題。
在ImageCache的OnImageCallbackListener的onImageLoaded函數中添加
Java 1 2 3 4 5 6 7 8 9 10 11 public void onImageLoaded ( String imageUrl , Drawable imageDrawable , View view , booleanisInCache ) { // can be another view child, like textView and so on if ( view != null && imageDrawable != null ) { ImageView imageView = ( ImageView ) view ; // add tag judge, avoid listView cache and so on String imageUrlTag = ( String ) imageView . getTag ( ) ; if ( ObjectUtils . isEquals ( imageUrlTag , imageUrl ) ) { imageView . setImageDrawable ( imageDrawable ) ; } } } ;在上面用String imageUrlTag = (String)imageView.getTag();取得之前設置的tag,然後和當前的url進行比較,如果相等則顯示,解決了b. 行item圖片顯示錯亂,c. 行item圖片顯示錯亂的兩個問題。其中ObjectUtils可見ObjectUtils@Github .
其他異步加載過程解決原理類似。
電腦控制Android設備的軟件——Total Control,androidtotal 最早開始搞Android開發時,為了調試方便,想找一個
Android 文件訪問權限的四種模式,android四種Linux文件的訪問權限* 在Android中,每一個應用是一個獨立的用戶* drwxrwxrwx* 第1位:d
AndroidAnnnotations注入框架使用之Injection標簽詳解(十) (一).前言: 前面我們已經對於AndroidAnnot
android app進行代碼混淆實例詳解 android app進行代碼混淆實例詳解 接到一個新的