Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android數據適配器(Adapter)優化:使用高效的ViewHolder

Android數據適配器(Adapter)優化:使用高效的ViewHolder

編輯:關於Android編程

更多內容請參照我的個人站點: http://stackvoid.com/

在使用Listview或GridView的時候,往往需要自定義數據適配器,一般都要覆寫getView(),在該方法中有一個convertView參數,該參數就是用來加載數據時的View。

初學者簡單但低效的方式

 1 public View getView(int position, View convertView, ViewGroup parent) {
 2  
 3  View item= inflater.inflate(R.layout.good_list_item, null, false);
 4       
 5  ImageView img = (ImageView) item.findViewById(R.id.img);
 6  TextView price = (TextView) item.findViewById(R.id.price);
 7  img.setImageResource(R.drawable.ic_launcher);
 8  price.setText("$"+list.get(position).price);
 9          
10  return item;
11 }

每次加載view,都要重新建立很多view對象,如果listview中有一萬條數據,並且每條view中的數據都比較復雜,這種加載方式就歇菜了。

利用convertView

利用convertView來重新回收View,效率有了本質提高。View的每次創建是比較耗時的,因此對於getview方法傳入的convertView應充分利用 != null的判斷 。

 1 public View getView(int position, View convertView, ViewGroup parent) {
 2 
 3      if(convertView==null){
 4          convertView = inflater.inflate(R.layout.good_list_item, null, false);
 5      }
 6      TextView tv_price = (TextView)convertView.findViewById(R.id.price)
 7      ImageView iv = (ImageView)convertView.findViewByID(R.id.img);
 8      
 9      return convertView;
10  }

使用ViewHolder

ViewHolder將需要緩存的view封裝好,convertView的setTag才是將這些緩存起來供下次調用。 當你的listview裡布局多樣化的時候 viewholder的作用體現明顯,效率再一次提高。 View的findViewById()方法也是比較耗時的,因此需要考慮只調用一次,之後就用View.getTag()方法來獲得ViewHolder對象。

 1 class ViewHolder{
 2      ImageView img;
 3      TextView price;
 4  }
 5 public View getView(int position, View convertView, ViewGroup parent) {
 6      ViewHolder holder = new ViewHolder();
 7      if(convertView==null){
 8          convertView = inflater.inflate(R.layout.good_list_item, null, false);
 9          holder.img = (ImageView) convertView.findViewById(R.id.img);
10          holder.price = (TextView) convertView.findViewById(R.id.price);
11          convertView.setTag(holder);  
12      }else{
13          holder = (ViewHolder) convertView.getTag();
14      }
15      //設置holder
16      holder.img.setImageResource(R.drawable.ic_launcher);
17      holder.price.setText("$"+list.get(position).price);
18          
19      return convertView;
20  }

優雅的使用ViewHolder

使用ViewHolder時,每次一遍一遍的findViewById,一遍一遍在ViewHolder裡面添加View的定義,view一多,是不是感覺煩爆了,base-adapter-helper這個類庫似乎完美的解決了這個問題。

其設計思想是使用 SparseArray來存儲view的引用,代替了原本的ViewHolder,不用聲明一大堆View,簡潔明了。

我也自己動手寫了一個簡單版的ViewHolder。

 1 public class ViewHolder{
 2  
 3     private final SparseArray views;
 4     private View convertView;
 5 
 6      private ViewHolder(View convertView){
 7         this.views = new SparseArray();
 8         this.convertView = convertView;
 9         convertView.setTag(this);
10     }
11 
12     public static ViewHolder get(View convertView){
13         if (convertView == null) {
14             return new ViewHolder(convertView);
15         }
16         ViewHolder existedHolder = (ViewHolder) convertView.getTag();
17         return existedHolder;
18     }
19  
20     public  T getView(int viewId) {
21         View view = views.get(viewId);
22         if (view == null) {
23             view = convertView.findViewById(viewId);
24             views.put(viewId, view);
25         }
26         return (T) view;
27     }
28 }

使用的話就超級簡單和簡潔了:

 1 public View getView(int position, View convertView, ViewGroup parent) {
 2         if (convertView == null) {
 3             convertView = LayoutInflater.from(context)
 4                     .inflate(R.layout.good_list_item, null, false);
 5         }
 6  
 7         ViewHolder mViewHolder = ViewHolder.get(convertView);
 8         TextView price = mViewHolder.getView(R.id.price);
 9         //...其他getView
10  
11         return convertView;
12     }

類似這種情況不要使用ViewHolder



更多內容請參照我的個人站點: http://stackvoid.com/

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved