zoukankan      html  css  js  c++  java
  • Android数据适配器(Adapter)优化:使用高效的ViewHolder

    原文链接:http://stackvoid.com/using-adapter-in-efficiency-way/

    在使用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<View> views;
     4     private View convertView;
     5 
     6      private ViewHolder(View convertView){
     7         this.views = new SparseArray<View>();
     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 extends View> 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/

  • 相关阅读:
    让div 充满整个body GIS
    fortuneclient 学习 (客户端接受数据) GIS
    错误 1 error C1083: 无法打开包括文件:“QNetworkProxy”: No such file or directory GIS
    qt fortuneserver 例子学习 ( 给客户端发送消息) GIS
    new操作符(new operator) 和 new操作(operator new)的区别。 GIS
    qt 控件 GIS
    c++ 顺序容器 GIS
    将一个div 分成两列 也可以分成多列 GIS
    控件模板 1
    WPF简单写写。。。
  • 原文地址:https://www.cnblogs.com/wzzkaifa/p/7238588.html
Copyright © 2011-2022 走看看