在任何项目中ListView无疑是用得最多的Android原生控件之一,ListView的使用方法、复用ConvertView、以及ViewHolder的使用这里就不再赘述了。
本文想要谈谈的是,当项目中反复使用到ListView时,如何对ListView进行封装,简化重复代码,提高效率。
class MyAdapter extends BaseAdapter { @Override public int getCount() { return data.size(); } @Override public Object getItem(int position) { return data.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if(convertView == null){ holder = new ViewHolder(); // 1.加载布局文件 View view = View.inflate(context, R.layout.listviewitem, null); // 2.初始化控件 holder.textView = view.findViewById(R.id.textView1); // 3.打一个tag标记 view.setTag(holder); }else{ holder = (ViewHolder) convertView.getTag(); } // 4.设置数据刷新内容 holder.textView.setText("设置内容"); return convertView; } } static class ViewHolder { TextView textView; }
但是如何封装呢?封装BaseAdapter最需要注意的方法就是getView()方法,但是我们可以看到,它一般的就是4个目的:
具体封装好的额两个MyBaseHolder和MyBaseAdapter直接先贴出来如下:
public abstract class MyBaseHolder<T> { // 一个item的根布局 private View mRootView; // 一个item的数据 private T data; // 当new这个对象时, 就会加载布局, 初始化控件,设置tag public MyBaseHolder() { mRootView = initView(); // 3. 打一个标记tag mRootView.setTag(this); } // 1. 加载布局文件 // 2. 初始化控件 findViewById public abstract View initView(); // 返回item的布局对象 public View getRootView() { return mRootView; } // 设置当前item的数据 public void setData(T data) { this.data = data; refreshView(data); } // 获取当前item的数据 public T getData() { return data; } // 4. 根据数据来刷新界面 public abstract void refreshView(T data); }
public abstract class MyBaseAdapter<T> extends BaseAdapter { private ArrayList<T> data; public MyBaseAdapter(ArrayList<T> data) { this.data = data; } @Override public int getCount() { return data.size(); } @Override public T getItem(int position) { return data.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { MyBaseHolder<T> baseHolder; if(convertView == null){ // 1. 加载布局文件 // 2. 初始化控件 findViewById // 3. 打一个标记tag baseHolder = getHolder(); }else{ baseHolder = (MyBaseHolder<T>) convertView.getTag(); } // 4. 设置内容刷新界面 baseHolder.setData(getItem(position)); return baseHolder.getRootView(); } public abstract MyBaseHolder<T> getHolder(); }
假设我的ListView里的item就是一个TextView,那么可以写一个ViewHolder如下:
public class SpecificHolder extends MyBaseHolder<String> { private TextView mTextView; @Override public View initView() { // 1. 加载布局 View view = View.inflate(null, R.layout.item_listview, null); // 2. 初始化控件 mTextView = (TextView) view.findViewById(R.id.textView1); return view; } @Override public void refreshView(String data) { // 3. 设置内容刷新界面 mTextView.setText(data); } }
那么最先贴出来的代码就可以改成如下了:
class MyAdapter extends MyBaseAdapter<String>{ public MyAdapter(ArrayList<String> data) { super(data); } @Override public MyBaseHolder<String> getHolder() { return new SpecificHolder(); } }
也许你已经乱了,我也是怕以后搞不清了就写个博客来加深记忆,也方便以后回忆。
我们来看下代码执行过程来一下: