• Android数据适配器(Adapter)优化:高效ViewHolder


    在使用Listview或GridView的时候,往往需要自定义数据适配器,一般都要覆写getView(),在该方法中有一个convertView参数,该参数就是用来加载数据时的View。

    在使用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中有一万条数据,这种加载方式就歇菜了。

    利用convertView

    利用Android的Recycler机制,利用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.      } 
  • 相关阅读:
    my eye
    html与HTML5的区别
    h5css样式
    h5css3弹性盒子
    简单js的介绍
    2020.8.16(周报6)
    2020.8.18
    2020.8.20
    2020.8.17
    2020.8.15
  • 原文地址:https://www.cnblogs.com/talon/p/4487307.html
Copyright © 2020-2023  润新知