在Android开发中,ListView被大量使用,ListView需要的情况多种多样。有时只需要简单的文字列表,有时需要将一个比较复杂的布局作为Item的内容,有时甚至需要不同类型,不同布局的内容交错排布在ListView中。按照通常的ListView优化策略会使用convertView和viewHolder来重用Item提升ListView的效率。但是,这样每一个布局不同的ListView我可能都需要写一个新的Adapter。如果还要在一个ListView中显示不同的布局则可能会产生大量的重复代码。因此,在这里我想换一个思路,暂时还没有经过足够的实践检验,它有可能是错的,我只是在此记录一下思路。
首先,每个ListView的Adapter真正需要输入的是什么?其实只有两个,一个是布局,一个是数据。Adapter的工作就是连接两者。因此,我希望Adapter中只有连接的内容。布局怎么实现,应该在布局中去写(因为可能有多种布局混在一个ListView中)。
接下来,数据的类型是未知的,我们只知道它应该是个List,然后List中包含了什么,我们不需要知道,每个布局去List里面找自己需要的东西就好了。
然后,每个布局都应该有一些公有的,必须实现的方法。比如:加载布局文件、获取布局中的控件、提取数据中的信息更新布局。
最后,Adapter只需要在getView中告诉布局,你现在去取数据List中第positon个数据来更新布局就可以了。
下面是代码
布局类
BaseAdapterViewHolder:
public abstract class BaseAdapterViewHolder { Context mContext; List<?> mDataList; View mConvertView; public BaseAdapterViewHolder(Context context , List<?> dataList , int convertViewId ){ mContext = context; mDataList = dataList; mConvertView = LayoutInflater.from(context).inflate(convertViewId , null); } public View getConvertView(){ return mConvertView; } abstract public void getItemChildView(View convertview); abstract public void setItemChlidView(int position); }
这个类是个虚拟类,在此记当一个子类的实现例子
public class DoufuItem2Data extends BaseAdapterViewHolder implements View.OnClickListener { ImageView userImage; TextView itemState; TextView itemUpdateTime; int mPositon; public DoufuItem2Data(Context context, List<?> dataList) { super(context, dataList, R.layout.doufu_itemview_test); } public void getItemChildView(View mConvertView) { userImage = (ImageView) mConvertView.findViewById(R.id.doufu_item_user_image); itemState = (TextView) mConvertView.findViewById(R.id.doufu_item_state); itemUpdateTime = (TextView) mConvertView.findViewById(R.id.doufu_item_update_time); } public void setItemChlidView(int position) { mPositon = position; itemState.setText("完结" + mPositon); itemUpdateTime.setText("更新 刚刚"); userImage.setOnClickListener(this); } @Override public void onClick(View v) { Toast.makeText(mContext, mDataList.get(mPositon).toString() + mPositon, Toast.LENGTH_SHORT).show(); } }
最后,附上这个布局类的Adapter中的使用方法:
public class DoufuFragmentListAdapter extends BaseAdapter { private Context mContext; private List<?> mDataList; public DoufuFragmentListAdapter(Context context , List<?> dataList) { mContext = context; mDataList = dataList; } @Override public int getCount() { return mDataList.size(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(final int position, View convertView, ViewGroup parent) { BaseAdapterViewHolder viewHolder; if(convertView == null){ viewHolder = new DoufuItem2Data(mContext , mDataList); convertView = viewHolder.getConvertView(); viewHolder.getItemChildView(convertView); convertView.setTag(viewHolder); } else{ viewHolder = (DoufuItem2Data) convertView.getTag(); } viewHolder.setItemChlidView(position); return convertView; } }
当我们需要使用不同的布局时,我们只需要将viewHolder = new DoufuItem2Data(mContext , mDataList);换成别的布局类即可。
Done!