一,概述
ListView在开发中是经常使用的。一般的方式是:创造一个类继承BaseAdapter。给ListView设置Adapter。Adapter是连接后端数据和前端显示的适配器接口,是数据和UI(View)之间一个重要的纽带。在常见的View(ListView,GridView)等地方都需要用到Adapter。Eg:过年包饺子,已经有了饺子皮和饺子馅,就缺包饺子的工具了。这个工具就可以类比Adapter,饺子馅就类比Data,饺子皮就类比UI。那么下面就摆脱原始的方式,对Adapter进行抽取,通过MVC模式code你的ListView。
二, 原始代码
1.布局
<ListView
android:id="@+id/main_listview"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
2.java代码
class MainAdapter extends BaseAdapter {
@Override
public int getCount() {
if (mData != null) {
return mData.size();
}
return 0;
}
@Override
public Object getItem(int position) {
if (mData != null) {
return mData.get(position);
}
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = View.inflate(getApplicationContext(),
R.layout.item_listview, null);
holder.tv1 = (TextView) convertView
.findViewById(R.id.item_tv_1);
holder.tv2 = (TextView) convertView
.findViewById(R.id.item_tv_2);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
String data = mData.get(position);
holder.tv1.setText("标题" + data);
holder.tv2.setText("正文" + data);
return convertView;
}
}
class ViewHolder {
private TextView tv1;
private TextView tv2;
}
三, BaseAdapter简单的抽取
1.创建BaseSuperAdapter继承BaseAdapter
BaseSuperAdpter<T> extends BaseAdapter{
List<T> mData;
public BaseSuperAdpter(List<T> data) {
mData = data;
}
2.MainAdater继承BaseSuperAdapter(是什么数据类型,就传什么数据类型)
class MainAdapter extends BaseSuperAdpter<String>
四,getView的抽取
- getView实际就干了两件事,inflateview和setData。
- 分析getView,有了View和数据,那么就可以做成MVC模式了,就缺一个控制器了。
- 从Holder入手,可以抽取成一个BaseHolder。作为控制器。
// 加载View
convertView = View.inflate(getApplicationContext(),
R.layout.item_listview, null);
holder.tv1 = (TextView) convertView
.findViewById(R.id.item_tv_1);
holder.tv2 = (TextView) convertView
.findViewById(R.id.item_tv_2);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// setData
String data = mData.get(position);
holder.tv1.setText("标题" + data);
holder.tv2.setText("正文" + data);
1.创建一个BaseHolder,BaseHolder的功能就是inflateview和setData了。
public abstract class BaseHolder<T> {
private View mRootView;
private T mData;
public BaseHolder(View rootView) {
mRootView = initView();
}
public View getRootView() {
return mRootView;
}
public void setData(T data) {
this.mData = data;
refreshUi(mData);
}
protected abstract void refreshUi(T data);
protected abstract View initView();}
- mRootView和setData这两个都是基类不确定的,所以做成抽象方法。
2.修改BaseSuperAdapter的getView中的方法
BaseHolder holder = null;
if(convertView == null){
holder = getItemHolder();
convertView = holder.getRootView();
convertView.setTag(holder);
}else{
holder = (BaseHolder) convertView.getTag();
}
T data = mData.get(position);
holder.setData(data);
return convertView;
}
protected abstract BaseHolder<T> getItemHolder();
- BaseHolder中的抽象方法initView和refreshUi在BaseSperHolder中也是无法确定的,所以写一个抽象方法holder是通过抽象方法getItemHolder()来得到的,让子类实现。
- MianAdapter就只剩下构造函数和getItemHolder()方法了。
class MainAdapter extends BaseSuperAdpter<String> {
public MainAdapter(List<String> data) {
super(data);
}
@Override
protected BaseHolder<String> getItemHolder() {
// TODO Auto-generated method stub
return null;
}}
- 所以只需要些一个Holder继承BaseAdapter传进来就可以了
3.写一个MaimHolder继承BaseHolder
public class MainHolder extends BaseHolder<String> {
private TextView mTv1;
private TextView mTv2;
@Override
protected View initView() {
View view = View.inflate(BaseApplication.getContext(), R.layout.item_listview, null);
mTv1 = (TextView) view.findViewById(R.id.item_tv_1);
mTv2 = (TextView) view.findViewById(R.id.item_tv_2);
return view;
}
@Override
protected void updateUI(String data) {
mTv1.setText("标题"+data);
mTv2.setText("正文"+data);
}}
- 在initView里面加载布局。
- 在updateUI里面设置数据,显示在UI上。