打造适配ListView的万能BaseAdapter

前言:我们项目中用ListView和RecyclerView的情况会非常多,每次写Adapter会不会觉得很繁琐,明明很多代码都差不多,本文将带领大家一步一步打造一个万能BaseListAdapter。

一:一般写法

  • MainActivity
public class MainActivity extends AppCompatActivity {

    private ListView lv_main;
    private List<Bean> mList;
    private PersonAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lv_main = findViewById(R.id.lv_main);

        initData();

        initView();

    }

    private void initData() {
        mList = new ArrayList<>();
        mList.add(new Bean("xiaoming 1", "湖南省长沙市天心区", 18));
        mList.add(new Bean("xiaoming 2", "湖南省长沙市天心区", 18));
        mList.add(new Bean("xiaoming 3", "湖南省长沙市天心区", 18));
        mList.add(new Bean("xiaoming 4", "湖南省长沙市天心区", 18));
        mList.add(new Bean("xiaoming 5", "湖南省长沙市天心区", 18));
        mList.add(new Bean("xiaoming 6", "湖南省长沙市天心区", 18));
    }

    private void initView() {
        mAdapter = new PersonAdapter(mList, this);
        lv_main.setAdapter(mAdapter);
    }
}

  • PersonAdapter
public class PersonAdapter extends BaseAdapter {

   private List<Bean> mList;
   private Context mContext;
   private LayoutInflater mInflater;

   public PersonAdapter(List<Bean> mList, Context context) {
       this.mList = mList;
       this.mContext = context;
       mInflater = LayoutInflater.from(context);
   }

   @Override
   public int getCount() {
       return (mList == null) ? 0 : mList.size();
   }

   @Override
   public Object getItem(int position) {
       return mList.get(position);
   }

   @Override
   public long getItemId(int position) {
       return position;
   }

   @Override
   public View getView(int position, View convertView, ViewGroup parent) {
       ViewHolder viewHolder = null;
       if (convertView == null) {
           convertView = mInflater.inflate(R.layout.item_list, parent, false);
           viewHolder = new ViewHolder();
           viewHolder.tv_name = convertView.findViewById(R.id.tv_name);
           viewHolder.tv_address = convertView.findViewById(R.id.tv_address);
           viewHolder.tv_age = convertView.findViewById(R.id.tv_age);
           convertView.setTag(viewHolder);
       } else {
           viewHolder = (ViewHolder) convertView.getTag(position);
       }

       Bean bean = mList.get(position);
       viewHolder.tv_name.setText(bean.getName());
       viewHolder.tv_address.setText(bean.getAddress());
       viewHolder.tv_age.setText("年龄:"+bean.getAge());

       return convertView;
   }


   private class ViewHolder {
       private TextView tv_name;
       private TextView tv_address;
       private TextView tv_age;
   }
}
  • 实体类Bean(基础和万能Adapter都一样)
public class Bean {
    private String name;
    private String address;
    private int age;
    ...//省略set,get和construct方法
}
  • xml布局(省略)
  • 运行效果
    在这里插入图片描述

二、把ViewHolder抽取出来,打造万能ViewHolder

  • 新建CommonViewHolder
public class CommonViewHolder {

    private SparseArray<View> mViews;
    private View mConvertView;
    private int mPosition;

    public CommonViewHolder(Context mContext, ViewGroup parent, int position, int resId) {
        this.mPosition = position;
        mViews = new SparseArray<>();
        mConvertView = LayoutInflater.from(mContext).inflate(resId, parent, false);
        mConvertView.setTag(this);
    }

    public static CommonViewHolder get(Context mContext, View convertView, ViewGroup parent, int position, int resId) {
        if (convertView == null) {
            return new CommonViewHolder(mContext, parent, position, resId);
        } else {
            CommonViewHolder viewHolder = (CommonViewHolder) convertView.getTag();
            viewHolder.mPosition = position;
            return viewHolder;
        }
    }

    /**
     * 通过VIewid获取控件
     *
     * @param viewId
     * @param <T>
     * @return
     */
    public <T extends View> T getView(int viewId) {
        T view = (T) mViews.get(viewId);
        if (view == null) {
            view = (T) mConvertView.findViewById(viewId);
            mViews.put(viewId, view);
        }
        return view;
    }


    public View getConvertView() {
        return mConvertView;
    }
}
  • 修改PersonAdapter中getView()代码
...//省略
 @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    //这边一句代码就做了上边获取ViewHolder的工作
        CommonViewHolder viewHolder = CommonViewHolder.get(mContext, convertView, parent, position, R.layout.item_list);

        Bean bean = mList.get(position);
        //使用CommonViewHolder中的getView方法设置数据
        ((TextView) viewHolder.getView(R.id.tv_name)).setText(bean.getName());
        ((TextView) viewHolder.getView(R.id.tv_address)).setText(bean.getAddress());
        ((TextView) viewHolder.getView(R.id.tv_age)).setText("年龄:" + bean.getAge());

        return viewHolder.getConvertView();
    }
    ...//省略
  • 次改后运行上述代码,发现运行成功。我们的代码简洁许多,万能ViewHolder初步打造完成。

三、完善CommonViewHolder,可以看到上部分有很多setText方法,我们将setText抽取出来,相应的还可以抽取setImageResource等等。

  • 修改CommonViewHolder
...//省略
 public  CommonViewHolder setText(int viewId,String text){
        ((TextView)getView(viewId)).setText(text);
        return this;
    }

    public CommonViewHolder setImageResource(int viewId,int resId){
        ((ImageView)getView(viewId)).setImageResource(resId);
        return this;
    }
    ...//省略
  • 相应修改PerAdapter代码
Bean bean = mList.get(position);
viewHolder.setText(R.id.tv_name,bean.getName())
                .setText(R.id.tv_address,bean.getAddress())
                .setText(R.id.tv_age,"年龄:" + bean.getAge());
  • 修改后运行成功,我们的CommonViewHolder打造完成,当然,除了setText、setImageResource,你还可以根据项目需要写一些需要的方法。

四、打造万能Adapter。(在写代码的过程中,我们会发现大部分的adapter,getCount、getItem、getItemId写的代码都差不多,初步我们就将它们提取出来)

  • 打造CommonListAdapter,提取getCount、getItem、getItemId
public abstract class CommonListAdapter<T> extends BaseAdapter {
    //泛型List
    private List<T> mDatas;

    public CommonListAdapter(List<T> mDatas) {
        this.mDatas = mDatas;
    }

    @Override
    public int getCount() {
        return (mDatas == null)?0:mDatas.size();
    }

    @Override
    public Object getItem(int position) {
        return mDatas.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public abstract View getView(int position, View convertView, ViewGroup parent);
}

  • 修改PersonAdapter代码
public class PersonAdapter extends CommonListAdapter {
    private Context mContext;
    private List<Bean> mList;

    public PersonAdapter(List mDatas,Context context) {
        super(mDatas);
        this.mContext = context;
        this.mList = mDatas;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        CommonViewHolder viewHolder = CommonViewHolder.get(mContext, convertView, parent, position, R.layout.item_list);

        Bean bean = mList.get(position);
        ((TextView) viewHolder.getView(R.id.tv_name)).setText(bean.getName());
        ((TextView) viewHolder.getView(R.id.tv_address)).setText(bean.getAddress());
        ((TextView) viewHolder.getView(R.id.tv_age)).setText("年龄:" + bean.getAge());

        return viewHolder.getConvertView();
    }
}
  • 运行代码,嗯,跟我们之前的效果一模一样,Adapter的代码量也相应减少。万能Adapter初步完成。

五、我们可以看到,CommonListAdapter中我们传递了数据mData,但是PersonAdapter的getView中依然要获取,而且viewHolder 和最后return也是差不多的写法,我们每次布局不可能一样,我们是否可以再次优化CommonListAdapter中的getView呢?

  • 再次优化CommonListAdapter
public abstract class CommonListAdapter<T> extends BaseAdapter {
    //泛型List
    private List<T> mDatas;
    private Context mContext;
    private int mLayoutId;

 public void setmDatas(List<T> mDatas) {
        this.mDatas = mDatas;
    }

    public CommonListAdapter(Context context,,int layoutId) {
        this.mContext = context;
        this.mLayoutId = layoutId;
    }

...//省略

    @Override
    public View getView(int position, View convertView, ViewGroup parent){
        CommonViewHolder viewHolder = CommonViewHolder.get(mContext, convertView, parent, position,mLayoutId);
        T bean = mDatas.get(position);

        convert(viewHolder,bean);

        return viewHolder.getConvertView();
    }

    public abstract void convert(CommonViewHolder viewHolder,T bean);
}

  • 再来写我们的PersonAdapter
public class PersonAdapter extends CommonListAdapter<Bean> {
    public PersonAdapter(List mDatas,Context context) {
       super(context,layoutId);
        setmDatas(mDatas);
    }
    
    @Override
    public void convert(CommonViewHolder viewHolder,Bean bean) {
        ((TextView) viewHolder.getView(R.id.tv_name)).setText(bean.getName());
        ((TextView) viewHolder.getView(R.id.tv_address)).setText(bean.getAddress());
        ((TextView) viewHolder.getView(R.id.tv_age)).setText("年龄:" + bean.getAge());
    }
}
  • 运行,效果杠杠滴(可以看到经过上述几部已经将PersonAdapter的代码简化简化再简化了,我们的CommonViewHolder和CommonListAdapter相信也可以满足大部分的项目需要了)。

六、有些ListView展示的数据很简单,我们就没有必要另外写一个类去继承CommonListAdapter了,直接使用匿名内部类会简单些。

  • 修改MainActivity代码
 private void initView() {
//        mAdapter = new PersonAdapter(mList, this);
//这里使用匿名内部类就不需要再去新建类
        lv_main.setAdapter(new CommonListAdapter<Bean>(mList,MainActivity.this,R.layout.item_list) {
            @Override
            public void convert(CommonViewHolder viewHolder, Bean bean) {
                viewHolder.setText(R.id.tv_name,bean.getName())
                        .setText(R.id.tv_address,bean.getAddress())
                        .setText(R.id.tv_age,"年龄:" + bean.getAge());
            }
        });
    }

七、总优化(延伸思考和总结)

  1. 思考:在实际使用过程中,因为还涉及到刷新,我们需要把数据提取出来单独写一个方法设置,还有我们ListVIew的多布局情况,如果用到这些都是需要考虑的。

  2. 总结:平时项目中用到了万能Adapter,也修改过其中的代码,这次看了慕课网的课程:https://www.imooc.com/learn/372
    完完整整的理了一遍,还是需要不断学习。请加油。

  3. 最后贴上demo下载地址,可直接下载运行 https://github.com/xiaomei888/baselistadapter/tree/master

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值