TShopping

 找回密碼
 註冊
搜索
查看: 269|回復: 0

[教學] Android中ViewHolder的使用

[複製鏈接]
發表於 2016-6-1 00:47:00 | 顯示全部樓層 |閱讀模式
 
Push to Facebook Push to Plurk Push to Twitter 
Android中GridView和ListView是最重要的兩種顯示內容的控件,在Android中,受限於手機屏幕的大小,使的不能像電腦一樣同時顯示多項內容。
   這兩者都需要一個adapter,可以是自定義適配器,也可以是BaseAdapter,SimpleAdapter,CursorAdapter。自定義適配器中,最為重要的是getView()方法,在該方法中有一個convertView參數,該參數就是用來加載數據時的View。
    在ListView中有時我們需要加載大量數據,如果每次都創建一個View,這樣會佔據大量內存,影響性能。這時就可以考慮用ViewHolder了。
      ViewHolder不是Android的開發API,而是一種設計方法,就是設計個靜態類,緩存一下,省得Listview更新的時候,還要重新操作。
  下面以listView加載方式比較一下viewholder的便利。
  viewholder的方式:將convetView的tag設置為ViewHolder,不為空時重新使用即可:


  1. class  ViewHolder{
  2.                         ImageView img;
  3.                         TextView  sitekey;
  4.                         TextView partname;
  5.                         TextView price;
  6.                         TextView value;
  7.                         TextView quantity_sold;
  8.                         TextView end_date;
  9.                         TextView jiantou;
  10.                 }
複製代碼


  1. public View getView(int position, View convertView, ViewGroup parent) {
  2.                         ViewHolder holder = new ViewHolder();
  3.                         if(convertView==null){
  4.                                 convertView = inflater.inflate(R.layout.good_list_item, null, false);
  5.                                 holder.img = (ImageView) convertView.findViewById(R.id.img);
  6.                                 holder.sitekey = (TextView) convertView.findViewById(R.id.sitekey);
  7.                                 holder.partname = (TextView) convertView.findViewById(R.id.partname);
  8.                                 holder.price = (TextView) convertView.findViewById(R.id.price);
  9.                                 holder.value = (TextView) convertView.findViewById(R.id.value);
  10.                                 holder.quantity_sold = (TextView) convertView.findViewById(R.id.quantity_sold);
  11.                                 holder.end_date = (TextView) convertView.findViewById(R.id.end_date);
  12.                                 holder.jiantou = (TextView) convertView.findViewById(R.id.jiantou);
  13.                                 convertView.setTag(holder);
  14.                         }else{
  15.                                 holder = (ViewHolder) convertView.getTag();
  16.                         }
  17.                         //设置holder
  18.                         holder.img.setImageResource(R.drawable.ic_launcher);
  19.                         holder.sitekey.setText(list.get(position).sitekey);
  20.                         holder.partname.setText(list.get(position).partname);
  21.                         holder.price.setText("$"+list.get(position).price);
  22.                         holder.value.setText("$"+list.get(position).value);
  23.                         holder.quantity_sold.setText("已售出:"+list.get(position).quantity_sold);
  24.                         holder.end_date.setText("截止日期:"+list.get(position).end_date);
  25.                        
  26.                        
  27.                         return convertView;
  28.                 }
複製代碼
錯誤的加載方式:每一次都重新定義一個View載入佈局,再加載數據:

  1. public View getView(int position, View convertView, ViewGroup parent) {
  2. View item = mInflater.inflate(R.layout.list_item_icon_text, null);
  3. ((TextView) item.findViewById(R.id.text)).setText(DATA[position]);
  4. ((ImageView) item.findViewById(R.id.icon)).setImageBitmap(
  5. (position & 1) == 1 ? mIcon1 : mIcon2);
  6. return item;
  7. }
複製代碼
正確的加載:當convertView不為空的時候直接重新使用convertView從而減少了很多不必要的View的創建,然後加載數據。

  1. public View getView(int position, View convertView, ViewGroup parent) {
  2. if (convertView == null) {
  3. convertView = mInflater.inflate(R.layout.item, parent, false);
  4. }
  5. ((TextView) convertView.findViewById(R.id.text)).setText(DATA[position]);
  6. ((ImageView) convertView.findViewById(R.id.icon)).setImageBitmap(
  7. (position & 1) == 1 ? mIcon1 : mIcon2);
  8. return convertView;
  9. }
複製代碼
convertView在API中的解釋是The old view to reuse, if possible,第一次getView時還沒有convertView,這時你便創建了一個新的view,下次getView時就有這個“舊的”convertView了setTag的作用才是把查找的view通過ViewHolder封裝好緩存起來方便 ​​多次重用,當需要時可以getTag拿出來
當你的listview里布局多樣化的時候viewholder的作用就有比較明顯的體現了。當然了,單一模式的佈局一樣有性能優化的作用只是不直觀。假如你2種模式的佈局當發生回收的時候你會用setTag分別記錄是哪兩種這兩種模式會被封裝到viewholder中進行保存方便你下次使用。所以當加載大量數據時,最好使用ViewHolder。


 

臉書網友討論
您需要登錄後才可以回帖 登錄 | 註冊 |

本版積分規則



Archiver|手機版|小黑屋|免責聲明|TShopping

GMT+8, 2016-12-7 06:09 , Processed in 0.056252 second(s), 22 queries .

本論壇言論純屬發表者個人意見,與 TShopping綜合論壇 立場無關 如有意見侵犯了您的權益 請寫信聯絡我們。

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表