zoukankan      html  css  js  c++  java
  • [Android]对BaseAdapter中ViewHolder编写简化

    以下内容为原创,欢迎转载,转载请注明

    来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3642849.html

    在Android项目中,经常都会用到ListView这个控件,而相应的Adapter中getView()方法的编写有一个标准的形式,如下:

     1 @Override
     2     public View getView(int position, View convertView, ViewGroup parent) {
     3         ViewHolder holder;
     4         if(null == convertView){
     5             holder = new ViewHolder();
     6             LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     7             convertView = mInflater.inflate(R.layout.item, null);
     8             holder.btn = (Button) convertView.findViewById(R.id.btn);
     9             holder.tv = (TextView) convertView.findViewById(R.id.tv);
    10             holder.iv = (TextView) convertView.findViewById(R.id.iv);
    11 
    12             convertView.setTag(holder);
    13         }else{
    14             holder = (ViewHolder) convertView.getTag();
    15         }
    16         final HashMap<String, Object> map = list.get(position);
    17 
    18         holder.iv.setImageResource(Integer.valueOf(map.get("iv").toString()));
    19         holder.tv.setText(map.get("tv").toString());
    20 
    21         holder.btn.setOnClickListener(new View.OnClickListener() {
    22             @Override
    23             public void onClick(View v) {
    24                 Toast.makeText(context, map.get("btn").toString(), Toast.LENGTH_SHORT).show();
    25             }
    26         });
    27 
    28         return convertView;
    29     }
    30 
    31     class ViewHolder{
    32         Button btn;
    33         ImageView iv;
    34         TextView tv;
    35 
    36     }

    以下是碎碎念(想直接看代码的,就跳过这段吧-_-!):

    也就是说每次编写Adapter都需要编写class ViewHolder...、if(null == convertView){...等等。这些代码跟业务逻辑关系不大,没有必要每次都写重复代码,

    所以,显然有简化代码的余地。

    既然我们的需求是不需要重复编写ViewHolder等内部类,那就把它移到父类吧。

    但是ViewHolder中在实际项目中有不同的View,那就用list存放起来吧,但是放在list中的话,怎么取出来?用index?显然不是好的方法,不是有Resource Id这玩意,通过这个取不就好了么?所以以Resource Id为key放在Map中比较合适,但是既然以int(Resource Id)为key,那自然而然想到使用SparseArray了。

    然后再把if(null == converView)...这些代码统统移到父类中。

    所以ABaseAdapter诞生了,代码如下:

     1 /**
     2  * 实现对BaseAdapter中ViewHolder相关的简化
     3  * Created with IntelliJ IDEA.
     4  * Author: wangjie  email:tiantian.china.2@gmail.com
     5  * Date: 14-4-2
     6  * Time: 下午5:54
     7  */
     8 public abstract class ABaseAdapter extends BaseAdapter{
     9     Context context;
    10 
    11     protected ABaseAdapter(Context context) {
    12         this.context = context;
    13     }
    14 
    15     protected ABaseAdapter() {
    16     }
    17 
    18     /**
    19      * 各个控件的缓存
    20      */
    21     public class ViewHolder{
    22         public SparseArray<View> views = new SparseArray<View>();
    23 
    24         /**
    25          * 指定resId和类型即可获取到相应的view
    26          * @param convertView
    27          * @param resId
    28          * @param <T>
    29          * @return
    30          */
    31         public <T extends View> T obtainView(View convertView, int resId){
    32             View v = views.get(resId);
    33             if(null == v){
    34                 v = convertView.findViewById(resId);
    35                 views.put(resId, v);
    36             }
    37             return (T)v;
    38         }
    39 
    40     }
    41 
    42     /**
    43      * 改方法需要子类实现,需要返回item布局的resource id
    44      * @return
    45      */
    46     public abstract int itemLayoutRes();
    47 
    48     @Override
    49     public View getView(int position, View convertView, ViewGroup parent) {
    50         ViewHolder holder;
    51         if(null == convertView){
    52             holder = new ViewHolder();
    53             convertView = LayoutInflater.from(context).inflate(itemLayoutRes(), null);
    54             convertView.setTag(holder);
    55         }else{
    56             holder = (ViewHolder) convertView.getTag();
    57         }
    58         return getView(position, convertView, parent, holder);
    59     }
    60 
    61     /**
    62      * 使用该getView方法替换原来的getView方法,需要子类实现
    63      * @param position
    64      * @param convertView
    65      * @param parent
    66      * @param holder
    67      * @return
    68      */
    69     public abstract View getView(int position, View convertView, ViewGroup parent, ViewHolder holder);
    70 
    71 }

    如上代码:增加了一个itemLayoutRes()的抽象方法,该抽象方法提供给子类实现,返回item布局的resource id,为后面的getView方法提供调用。

    可以看到上述代码中,在系统的getView方法中,进行我们以前在BaseAdapter实现类中所做的事(初始化converView,并绑定ViewHolder作为tag),然后抛弃了系统提供的getView方法,直接去调用自己写的getView抽象方法,这个getView方法是提供给子类去实现的,作用跟系统的getView一样,但是这个getView方法中携带了一个ViewHolder对象,子类可以通过这个对象进行获取item中的控件。

    具体使用方式如下,比如创建了MyAdapter并继承了ABaseAdapter:

    注意,在构造方法中需要调用父类的构造方法:

    1 public MyAdapter(Context context, List<HashMap<String, Object>> list) {
    2     super(context);
    3     this.list = list;
    4 }

    即,以上的“super(context);”必须调用。

    接着实现itemLayoutRes()方法,返回item的布局:

    1 @Override
    2 public int itemLayoutRes() {
    3     return R.layout.item;
    4 }

    getView方法中的实现如下:

     1 @Override
     2 public View getView(int position, View convertView, ViewGroup parent, ViewHolder holder) {
     3     final HashMap<String, Object> map = list.get(position);
     4 
     5     Button btn = holder.obtainView(convertView, R.id.item_btn);
     6     ImageView iv = holder.obtainView(convertView, R.id.item_iv);
     7     TextView tv = holder.obtainView(convertView, R.id.item_tv);
     8 
     9      btn.setOnClickListener(new View.OnClickListener() {
    10         @Override
    11         public void onClick(View v) {
    12             Toast.makeText(context, map.get("btn").toString(), Toast.LENGTH_SHORT).show();
    13          }
    14      });
    15 
    16      iv.setImageResource(Integer.valueOf(map.get("iv").toString()));
    17      tv.setText(map.get("tv").toString());
    18 
    19         return convertView;
    20     }

    如上代码:调用holder.obtainView方法既可获取item中的控件;

  • 相关阅读:
    互联网架构 高可用和高并发 (转)
    mysql数据库索引
    SQL小结
    limit小结
    JDK8 元空间
    OpenStack基础知识
    shell 发送所有内容到会话
    通过word给博客园发布文章教程
    centos7.4安装过程
    Zabbix 调整告警发送的内容格式
  • 原文地址:https://www.cnblogs.com/tiantianbyconan/p/3642849.html
Copyright © 2011-2022 走看看