ListView 優(yōu)化之 ViewHolder 復用機制

ViewHolder 復用機制

在使用 ListView 過程中適配器 Adapter 中的 getView() 方法中已經(jīng)通過 convertView 復用機制(RecycleBin 回收再利用) 進行了優(yōu)化烤送。

但我們發(fā)現(xiàn)代碼中仍然存在可以改進的地方,觀察如下代碼

public View getView(int position, View convertView, ViewGroup parent) {  
    Fruit fruit = getItem(position);  
    View view;  
    if (convertView == null) {  
        view = LayoutInflater.from(getContext()).inflate(resourceId, null);  
    } else {  
        view = convertView;  
    }  
    ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);  
    TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);  
    fruitImage.setImageResource(fruit.getImageId());  
    fruitName.setText(fruit.getName());  
    return view;  
} 

我們發(fā)現(xiàn)雖然 convertView 是實現(xiàn)了復用,但是每次 getView() 時鹅搪,都要對每個子 View 中包含的控件進行實例化(findViewById)操作,這也是一個耗時的操作翁巍,這里就使用到了 ViewHolder 這個類來進行優(yōu)化操作子姜。

    public View getView(int position, View convertView, ViewGroup parent) {
         System.out.println("getView " + position + " " + convertView);
         ViewHolder holder = null;
         if (convertView == null) {
             convertView = mInflater.inflate(R.layout.lv_item, null);
             holder = new ViewHolder();
             holder.textView = (TextView)convertView.findViewById(R.id.tv_text);
             convertView.setTag(holder);
         } else {
             holder = (ViewHolder)convertView.getTag();
         }
         holder.textView.setText(mData.get(position));
         return convertView;
     }
}

 public static class ViewHolder {
     public TextView textView;
 }

如上代碼所述,我們把每個子 View 中包含的控件(需要實例化的)都放到 ViewHolder 的靜態(tài)內(nèi)部類中弓叛。當?shù)谝淮蝿?chuàng)建 convertView 對象時,把 ViewHolder 中的控件都進行實例化诚纸,然后用 convertView 的 setTag() 方法將 ViewHolder 設(shè)置到 Tag 中撰筷,以便系統(tǒng)第二次調(diào)用 getView() 方法時子 View 中需要的控件可以直接通過 convertView.getTag() 方法取出 ViewHolder 容器對象,然后直接調(diào)用需要的控件即可畦徘。

ListView 中的 convertView 和 ViewHolder 協(xié)同
ListView 里面的每一個 item 都是通過 adapter 來得到的毕籽,然后根據(jù) listView 的高度和 item 的高度來循環(huán)加載顯示在 listView 上抬闯,因此首次加載就決定了能夠顯示出來的 item 的個數(shù),并且首次走進的都是 getView() 方法里 convertView==null 的時候关筒,也就是說溶握,此時加載了幾個 item(包括只顯示一部分的),就創(chuàng)建了幾個 ViewHolder 對象蒸播,ViewHolder 里的控件來指向?qū)?yīng)的 convertView 里的控件睡榆。

image.png

圖中顯示了 ListView 顯示出的6個 item,和對應(yīng)生成的6個 ViewHolder 對象廉赔。并且在 ListView 工作過程中一直指向它們各自的 item肉微。注意此時,RecycleBin 里還么有任何可以拿來復用的 convertView蜡塌。若此時碉纳,ListView 向上滑動一部分,使得 item 1 一部分滾出 ListView 的 頂部馏艾,并且 item 7 也進入一部分劳曹,因為此時 RecycleBin 里沒有任何可以復用的 convertView(廢棄緩存里沒有 View),所以琅摩,程序急促進入 convertView == null铁孵,ViewHolder 7也被創(chuàng)建,指向 item 7房资。如果此時繼續(xù)滑動 item 1蜕劝,使得頁面剛好顯示的是 item2-7, 將不會再生成新的 ViewHolder轰异。此時滾出去的 item 1對應(yīng)的 View 將被放入 RecycleBin 里面做備用的 convertView 1岖沛,如果繼續(xù)往上滑動,item 8即將進入 ListView搭独,此時 ListView 的 adapter 在 RecycleBin 里找到了可以復用的 convertView 1婴削,而且因為之前用了 setTag 的方式,因此可以用 getTag 迅速獲得 ViewHolder 1牙肝,并且 ViewHolder 1是始終指向 convertView 1唉俗,因此直接可以根據(jù) position 來設(shè)置對應(yīng)的圖片,文本然后 return 此更新后的 View 給 ListView 來顯示 item 8配椭。

做 ViewHolder 來優(yōu)化 ListView 時虫溜,需要用 static 來修飾 ViewHolder 類?

我們把 ViewHolder 類設(shè)置成 static 靜態(tài)類颂郎,是想讓整個內(nèi)存中之需要一份 ViewHolder 對象吼渡,來優(yōu)化 ListView。

但是通過實驗發(fā)現(xiàn)

    //把ViewHolder變?yōu)閟tatic之后乓序,getView()里加上如下代碼:
viewHolder = new ViewHolder();
AppLog.i("viewHolder" + i +" = " + viewHolder );
i++;

20.548 12491-12491/?  [getView()] - viewHolder1 = $ViewHolder@e6a668d
20.627 12491-12491/?  [getView()] - viewHolder2 = $ViewHolder@22e2da45
20.629 12491-12491/?  [getView()] - viewHolder3 = $ViewHolder@355bd5c1
20.632 12491-12491/?  [getView()] - viewHolder4 = $ViewHolder@210f0cfd
20.635 12491-12491/?  [getView()] - viewHolder5 = $ViewHolder@3c47bf9
20.637 12491-12491/?  [getView()] - viewHolder6 = $ViewHolder@35c7deb5
20.640 12491-12491/?  [getView()] - viewHolder7 = $ViewHolder@e64b131
20.642 12491-12491/?  [getView()] - viewHolder8 = $ViewHolder@34222f6d
20.644 12491-12491/?  [getView()] - viewHolder9 = $ViewHolder@34bf5569
20.647 12491-12491/?  [getView()] - viewHolder10 = $ViewHolder@20eedf25
20.650 12491-12491/?  [getView()] - viewHolder11 = $ViewHolder@27d348a1
20.653 12491-12491/?  [getView()] - viewHolder12 = $ViewHolder@2e3acddd
20.656 12491-12491/?  [getView()] - viewHolder13 = $ViewHolder@3290cc9e
40.937 12491-12491/: [MainActivity$1:48 onScrollStateChanged()] - scroll
44.879 12491-12491/: [MainActivity$1:52 onScrollStateChanged()] - fling
44.994 12491-12491/: [MainActivity$1:44 onScrollStateChanged()] - idle

靜態(tài)內(nèi)部類的實例地址都是不一樣的寺酪,所以并沒有優(yōu)化 ViewHolder 的個數(shù)。然而實際情況是因為 convertView 的復用機制替劈,convertView 不會太多寄雀,一般情況下=ListView 顯示的 item 個數(shù) + 1*viewTypeCount。所以 ViewHolder 的個數(shù)也不會太多陨献。所以沒有優(yōu)化的意義盒犹。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市眨业,隨后出現(xiàn)的幾起案子急膀,更是在濱河造成了極大的恐慌,老刑警劉巖龄捡,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卓嫂,死亡現(xiàn)場離奇詭異,居然都是意外死亡聘殖,警方通過查閱死者的電腦和手機晨雳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來奸腺,“玉大人餐禁,你說我怎么就攤上這事⊥徽眨” “怎么了帮非?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長讹蘑。 經(jīng)常有香客問我末盔,道長,這世上最難降的妖魔是什么衔肢? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任庄岖,我火速辦了婚禮,結(jié)果婚禮上角骤,老公的妹妹穿的比我還像新娘隅忿。我一直安慰自己,他們只是感情好邦尊,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布背桐。 她就那樣靜靜地躺著,像睡著了一般蝉揍。 火紅的嫁衣襯著肌膚如雪链峭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天又沾,我揣著相機與錄音弊仪,去河邊找鬼熙卡。 笑死,一個胖子當著我的面吹牛励饵,可吹牛的內(nèi)容都是我干的驳癌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼役听,長吁一口氣:“原來是場噩夢啊……” “哼颓鲜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起典予,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤甜滨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后瘤袖,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衣摩,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年孽椰,在試婚紗的時候發(fā)現(xiàn)自己被綠了昭娩。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡黍匾,死狀恐怖栏渺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情锐涯,我是刑警寧澤磕诊,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站纹腌,受9級特大地震影響霎终,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜升薯,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一莱褒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧涎劈,春花似錦广凸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蹦浦,卻和暖如春扭吁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工侥袜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蝌诡,地道東北人。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓系馆,卻偏偏與公主長得像送漠,于是被迫代替她去往敵國和親顽照。 傳聞我的和親對象是個殘疾皇子由蘑,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容