Android BaseAdapter的極簡封裝
目的:
- 減少Adapter基礎邏輯重複書寫
- 優化Adapter結構 使得代碼更清晰
- 将通用邏輯封裝 集中優化處理 減少不必要環節出錯
方式:
- 泛型傳參
- 使用抽象類
- 父類封裝通用邏輯
- 子類隻需實作抽象方法 而不必關注 Adapter 内部具體處理邏輯
不廢話,直接看代碼:
父類 抽象類SuperBaseAdapter.java:
/**
* BaseAdapter for listView gridView
* Author: liangjin.bai
* Email: [email protected]
* Create Time: 2015/10/9 18:23
*/
public abstract class SuperBaseAdapter<T> extends BaseAdapter {
protected final Context context;
protected final LayoutInflater mLayoutInflater;
protected List<T> dataList;
public SuperBaseAdapter(Activity activity, List<T> dataList) {
this.context = activity;
this.dataList = dataList;
mLayoutInflater = LayoutInflater.from(this.context);
}
@Override
public int getCount() {
return dataList == null ? : dataList.size();
}
@Override
public T getItem(int position) {
return dataList == null ? null : dataList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHelper viewHelper = new ViewHelper(convertView, parent).invoke();
convertView = viewHelper.getConvertView();
T item = getItem(position);
Object holder = viewHelper.getHolder();
setItemData(item, holder);
return convertView;
}
public void setListData(List<T> dataList) {
this.dataList = dataList;
notifyDataSetChanged();
}
/**
* 擷取 item layout ResId
*
* @return int item layout resid
*/
public abstract int getItemLayoutResId();
/**
* 擷取 ViewHolder ViewHolder自身實作初始化
*
* @param rootView
* @return
*/
public abstract Object getViewHolder(View rootView);
/**
* 設定item資料
*
* @param dataItem
* @param viewHolder
*/
public abstract void setItemData(T dataItem, Object viewHolder);
/**
* 實作中間環節的調用輔助類
*/
private class ViewHelper {
private View convertView;
private ViewGroup viewGroup;
private Object holder;
public ViewHelper(View convertView, ViewGroup viewGroup) {
this.convertView = convertView;
this.viewGroup = viewGroup;
}
public View getConvertView() {
return convertView;
}
public Object getHolder() {
return holder;
}
public ViewHelper invoke() {
//covertView 複用的邏輯在這裡呢 再也不用一遍一遍的寫這個邏輯了
if (convertView == null) {
//建立 convertView
convertView = mLayoutInflater.inflate(getItemLayoutResId(), viewGroup, false);
holder = getViewHolder(convertView);
convertView.setTag(holder);
} else {
//複用 convertView
holder = convertView.getTag();
}
return this;
}
}
}
子類 示例Adapter DemoAdapter.java:
/**
* 示例Adapter 類
* Author: liangjin.bai
* Email: [email protected]
* Create Time: 2015/10/9 18:25
*/
public class DemoAdapter extends SuperBaseAdapter {
public DemoAdapter(Activity context, List<GroupModel> list) {
super(context,list);
}
@Override
public int getItemLayoutResId() {
return R.layout.item_group_list;
}
@Override
public Object getViewHolder(View rootView) {
//傳回自己的 ViewHolder對象
return new ViewHolder(rootView);
}
@Override
public void setItemData(Object dataItem, Object viewHolder) {
GroupModel groupModel = (GroupModel) dataItem;
//将holder 轉為自己holder
ViewHolder myHolder = (ViewHolder) viewHolder;
myHolder.tv_group_name.setText(TextUtils.isEmpty(groupModel.getContactName()) ? "" : groupModel.getContactName());
//ImageLoadUtils.loadImage(myHolder.iv_group_avatar, groupModel.getHeadUrl());
myHolder.iv_group_no_disturb.setVisibility(groupModel.getIsDisturb() == ? View.VISIBLE : View.GONE);
}
/**
* ViewHolder 通過構造方法中 實作具體view的綁定的方式 建立一個自實作綁定View的ViewHolder
* Created by bailiangjin on 16/7/5.
*/
public static class ViewHolder {
public final View root;
public final ImageView iv_group_avatar;
public final ImageView iv_group_no_disturb;
public final TextView tv_group_name;
public ViewHolder(View root) {
this.root = root;
this.iv_group_avatar = (ImageView) this.root.findViewById(R.id.iv_group_avatar);
this.iv_group_no_disturb = (ImageView) this.root.findViewById(R.id.iv_group_no_disturb);
this.tv_group_name = (TextView) this.root.findViewById(R.id.tv_group_name);
}
}
xml資源檔案:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@color/white"
android:layout_height="58dp">
<ImageView
android:id="@+id/iv_group_avatar"
android:layout_width="50dp"
android:layout_alignParentLeft="true"
android:layout_marginLeft="16dp"
android:layout_centerVertical="true"
android:src="@drawable/nomal_head"
android:layout_height="50dp" />
<TextView
android:id="@+id/tv_group_name"
android:layout_toRightOf="@+id/iv_group_avatar"
android:layout_width="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:text="群名稱"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/iv_group_no_disturb"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="16dp"
android:src="@drawable/icon_group_no_disturb"
android:layout_centerVertical="true"
android:layout_height="wrap_content" />
</RelativeLayout>
總結
觀察DemoAdapter 可以發現 繼承成 SuperBaseAdapter 後 不再需要 關注view 的複用問題 複用邏輯已經在父類實作;
子類需要實作的方法其實隻有:
1、在getItemLayoutResId() 方法中 傳回 Adapter 使用的View 的layout resId;
2、建立自己的ViewHolder 傳回給父類 建立新convert view時使用;
3、在 setItemData()回調方法中 對item 的資料進行填充
其他 layoutInflater、getView、getItem等等方法以及 convert view複用等繁雜備援的邏輯再也不需要關注,關注核心業務,從繁雜的功能代碼中解放出來。
代碼連結
以上隻是關于Android 項目重構的一小部分,更多的可以關注我再Github上的一個Android 基礎資源庫的項目BaseLibrary:
點選檢視 BaseLibrary源碼
上面講的BaseAdpter部分源碼請點選這個連結連結:
點選檢視 BaseAdpter部分源碼連結
點選檢視 我的博文目錄