高靈活低耦合Adapter快速開發攻略

Android開發中經常需要使用Adapter。

傳統方法是自定義一個Adapter並繼承AndroidSDK內的BaseAdapter,

這種方式代碼量大,耦合度高,靈活性差(各種監聽事件需要對View單獨寫,或者自定義一個比較統一的方法);

 

而ZBLibrary中的BaseViewAdapter不僅預處理了通用方法(getCount,getItem等) 以及 Item複用邏輯,

而且將對Item的處理代碼單獨寫在一個BaseView(提供了大量常用方法)的子類,

所以使用繼承BaseViewAdapter的新方式能大幅精簡代碼,並且帶來高靈活性和低耦合度。

 

比如這個界面

 

傳統方式實現的CommonAdapter代碼如下

  1 package com.example.quickadapter;
  2 
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 
  6 import zuo.biao.library.ui.WebViewActivity;
  7 import zuo.biao.library.util.ImageLoaderUtil;
  8 import android.app.Activity;
  9 import android.view.LayoutInflater;
 10 import android.view.View;
 11 import android.view.View.OnClickListener;
 12 import android.view.ViewGroup;
 13 import android.widget.BaseAdapter;
 14 import android.widget.ImageView;
 15 import android.widget.TextView;
 16 
 17 public class CommonAdapter extends BaseAdapter {
 18 
 19     private Activity context;
 20     private List<User> list;
 21     private LayoutInflater inflater;
 22     public CommonAdapter(Activity context, List<User> list) {
 23         this.context = context;
 24         this.list = new ArrayList<>(list);
 25         this.inflater = context.getLayoutInflater();
 26     }
 27 
 28     @Override
 29     public int getCount() {
 30         return list.size();
 31     }
 32 
 33     @Override
 34     public User getItem(int position) {
 35         return list.get(position);
 36     }
 37 
 38     @Override
 39     public long getItemId(int position) {
 40         return position;
 41     }
 42 
 43     public synchronized void refresh(List<User> list) {
 44         if (list != null && list.size() > 0) {
 45             this.list = new ArrayList<>(list);
 46         }
 47         notifyDataSetChanged();
 48     }
 49 
 50     @Override
 51     public View getView(final int position, View convertView, ViewGroup parent) {
 52         ViewHolder holder = convertView == null ? null : (ViewHolder) convertView.getTag();
 53         if (holder == null) {
 54             convertView = inflater.inflate(R.layout.user_item, parent, false);
 55             holder = new ViewHolder();
 56 
 57             holder.ivUserItemHead = (ImageView) convertView.findViewById(R.id.ivUserItemHead);
 58             holder.ivUserItemStar = (ImageView) convertView.findViewById(R.id.ivUserItemStar);
 59 
 60             holder.tvUserItemSex = (TextView) convertView.findViewById(R.id.tvUserItemSex);
 61 
 62             holder.tvUserItemName = (TextView) convertView.findViewById(R.id.tvUserItemName);
 63             holder.tvUserItemId = (TextView) convertView.findViewById(R.id.tvUserItemId);
 64             holder.tvUserItemNumber = (TextView) convertView.findViewById(R.id.tvUserItemNumber);
 65 
 66             convertView.setTag(holder);
 67         }
 68 
 69         final User user = getItem(position);
 70 
 71         ImageLoaderUtil.loadImage(holder.ivUserItemHead, user.getHead(), ImageLoaderUtil.TYPE_OVAL);
 72         holder.ivUserItemStar.setImageResource(user.getStarred() ? R.drawable.star_light : R.drawable.star);
 73 
 74         holder.tvUserItemSex.setBackgroundResource(user.getSex() == User.SEX_FEMAIL ? R.drawable.circle_pink : R.drawable.circle_blue);
 75         holder.tvUserItemSex.setText(user.getSex() == User.SEX_FEMAIL ?  "女" : "男");
 76         holder.tvUserItemSex.setTextColor(context.getResources().getColor(user.getSex() == User.SEX_FEMAIL ? R.color.pink : R.color.blue));
 77         
 78         holder.tvUserItemName.setText("" + user.getName());
 79         holder.tvUserItemId.setText("ID:" + user.getId());
 80         holder.tvUserItemNumber.setText("Phone:" + user.getPhone());
 81 
 82         holder.ivUserItemHead.setOnClickListener(new OnClickListener() {
 83 
 84             @Override
 85             public void onClick(View v) {
 86                 context.startActivity(WebViewActivity.createIntent(context, user.getName(), user.getHead()));
 87             }
 88         });
 89 
 90         holder.ivUserItemStar.setOnClickListener(new OnClickListener() {
 91 
 92             @Override
 93             public void onClick(View v) {
 94                 user.setStarred(! user.getStarred());
 95                 list.set(position, user);
 96                 refresh(null);
 97             }
 98         });
 99 
100         holder.tvUserItemSex.setOnClickListener(new OnClickListener() {
101 
102             @Override
103             public void onClick(View v) {
104                 user.setSex(user.getSex() == User.SEX_FEMAIL ? User.SEX_MAIL : User.SEX_FEMAIL);
105                 list.set(position, user);
106                 refresh(null);
107             }
108         });
109 
110         return convertView;
111     }
112 
113     class ViewHolder {
114         public ImageView ivUserItemHead;
115         public ImageView ivUserItemStar;
116 
117         public TextView tvUserItemSex;
118 
119         public TextView tvUserItemName;
120         public TextView tvUserItemId;
121         public TextView tvUserItemNumber;
122     }
123 }

 

繼承BaseViewAdapter的新方式實現的QuickAdapter代碼如下

  1 package com.example.quickadapter;
  2 
  3 import java.util.List;
  4 
  5 import zuo.biao.library.base.BaseView;
  6 import zuo.biao.library.base.BaseViewAdapter;
  7 import zuo.biao.library.ui.WebViewActivity;
  8 import zuo.biao.library.util.ImageLoaderUtil;
  9 import zuo.biao.library.util.StringUtil;
 10 import android.annotation.SuppressLint;
 11 import android.app.Activity;
 12 import android.content.res.Resources;
 13 import android.view.LayoutInflater;
 14 import android.view.View;
 15 import android.view.View.OnClickListener;
 16 import android.view.ViewGroup;
 17 import android.widget.ImageView;
 18 import android.widget.TextView;
 19 
 20 import com.example.quickadapter.QuickAdapter.UserView;
 21 
 22 public class QuickAdapter extends BaseViewAdapter<User, UserView> {
 23 
 24     public QuickAdapter(Activity context, List<User> list) {
 25         super(context, list);
 26     }
 27 
 28     @Override
 29     public UserView createView(int position, View convertView, ViewGroup parent) {
 30         return new UserView(context, resources);
 31     }
 32 
 33     public class UserView extends BaseView<User> implements OnClickListener {
 34         public UserView(Activity context, Resources resources) {
 35             super(context, resources);
 36         }
 37 
 38         public ImageView ivUserViewHead;
 39         public ImageView ivUserViewStar;
 40         
 41         public TextView tvUserViewSex;
 42 
 43         public TextView tvUserViewName;
 44         public TextView tvUserViewId;
 45         public TextView tvUserViewNumber;
 46         @SuppressLint("InflateParams")
 47         @Override
 48         public View createView(LayoutInflater inflater) {
 49             convertView = inflater.inflate(R.layout.user_view, null);
 50 
 51             ivUserViewHead = findViewById(R.id.ivUserViewHead, this);
 52             ivUserViewStar = findViewById(R.id.ivUserViewStar, this);
 53 
 54             tvUserViewSex = findViewById(R.id.tvUserViewSex, this);
 55             
 56             tvUserViewName = findViewById(R.id.tvUserViewName);
 57             tvUserViewId = findViewById(R.id.tvUserViewId);
 58             tvUserViewNumber = findViewById(R.id.tvUserViewNumber);
 59 
 60             return convertView;
 61         }
 62 
 63         @Override
 64         public void setView(User data){
 65             if (data == null) {
 66                 return;
 67             }
 68             this.data = data;
 69 
 70             ImageLoaderUtil.loadImage(ivUserViewHead, data.getHead(), ImageLoaderUtil.TYPE_OVAL);
 71             ivUserViewStar.setImageResource(data.getStarred() ? R.drawable.star_light : R.drawable.star);
 72             
 73             tvUserViewSex.setBackgroundResource(data.getSex() == User.SEX_FEMAIL ? R.drawable.circle_pink : R.drawable.circle_blue);
 74             tvUserViewSex.setText(data.getSex() == User.SEX_FEMAIL ?  "女" : "男");
 75             tvUserViewSex.setTextColor(getColor(data.getSex() == User.SEX_FEMAIL ? R.color.pink : R.color.blue));
 76             
 77             tvUserViewName.setText(StringUtil.getTrimedString(data.getName()));
 78             tvUserViewId.setText("ID:" + data.getId());
 79             tvUserViewNumber.setText("Phone:" + StringUtil.getNoBlankString(data.getPhone()));
 80         }
 81 
 82         @Override
 83         public void onClick(View v) {
 84             if (data == null) {
 85                 return;
 86             }
 87             switch (v.getId()) {
 88             case R.id.ivUserViewHead:
 89                 toActivity(WebViewActivity.createIntent(context, data.getName(), data.getHead()));
 90                 break;
 91             case R.id.ivUserViewStar:
 92                 data.setStarred(! data.getStarred());
 93                 setView(data);
 94                 break;
 95             case R.id.tvUserViewSex:
 96                 data.setSex(data.getSex() == User.SEX_FEMAIL ? User.SEX_MAIL : User.SEX_FEMAIL);
 97                 setView(data);
 98                 break;
 99             default:
100                 break;
101             }        
102         }
103     }
104 }


 

 

看下ZBLibrary中的BaseView,裏面有大量常用的 且 AndroidSDK內的BaseAdapter沒有提供的 方法。

package zuo.biao.library.base;

import zuo.biao.library.util.CommonUtil;
import zuo.biao.library.util.Log;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;

/**基礎自定義View
 * @author Lemon
 * @param <T> 數據模型(model/JavaBean)類
 * @see #onDestroy
 * @use extends BaseView<T>, 具體參考.DemoView
 */
public abstract class BaseView<T> {
	private static final String TAG = "BaseView";

	/**
	 * 傳入的Activity,可在子類直接使用
	 */
	protected Activity context;
	protected Resources resources;
	public BaseView(Activity context, Resources resources) {
		this.context = context;
		this.resources = resources == null ? context.getResources() : resources;
	}

	/**數據改變回調接口
	 * (Object) getData() - 改變的數據
	 */
	public interface OnDataChangedListener {
		void onDataChanged();
	}

	public OnDataChangedListener onDataChangedListener;//數據改變回調監聽類的實例
	/**設置數據改變事件監聽類
	 * @param l
	 */
	public void setOnDataChangedListener(OnDataChangedListener l) {
		onDataChangedListener = l;
	}

	public OnTouchListener onTouchListener;//接觸View回調監聽類的實例
	/**設置接觸View事件監聽類
	 * @param l
	 */
	public void setOnTouchListener(OnTouchListener l) {
		onTouchListener = l;
	}

	public OnClickListener onClickListener;//點擊View回調監聽類的實例
	/**設置點擊View事件監聽類
	 * @param l
	 */
	public void setOnClickListener(OnClickListener l) {
		onClickListener = l;
	}

	public OnLongClickListener onLongClickListener;//長按View回調監聽類的實例
	/**設置長按View事件監聽類
	 * @param l
	 */
	public void setOnLongClickListener(OnLongClickListener l) {
		onLongClickListener = l;
	}



	/**
	 * 子類整個視圖,可在子類直接使用
	 * @must createView方法內對其賦值且不能爲null
	 */
	protected View convertView = null;

	/**通過id查找並獲取控件,使用時不需要強轉
	 * @param id
	 * @return 
	 */
	@SuppressWarnings("unchecked")
	public <V extends View> V findViewById(int id) {
		return (V) convertView.findViewById(id);
	}
	/**通過id查找並獲取控件,並setOnClickListener
	 * @param id
	 * @param l
	 * @return
	 */
	public <V extends View> V findViewById(int id, OnClickListener l) {
		V v = findViewById(id);
		v.setOnClickListener(l);
		return v;
	}
	/**創建一個新的View
	 * @return
	 */
	public abstract View createView(@NonNull LayoutInflater inflater);

	/**獲取convertView的寬度
	 * @warn 只能在createView後使用
	 * @return
	 */
	public int getWidth() {
		return convertView.getWidth();
	}
	/**獲取convertView的高度
	 * @warn 只能在createView後使用
	 * @return
	 */
	public int getHeight() {
		return convertView.getHeight();
	}

	/**
	 * data在列表中的位置
	 * @must 只使用setView(int position, T data)方法來設置position,保證position與data對應正確
	 */
	protected int position = 0;
	/**獲取data在列表中的位置
	 */
	public int getPosition() {
		return position;
	}

	protected T data = null;
	/**獲取數據
	 * @return
	 */
	public T getData() {
		return data;
	}

	/**設置並顯示內容
	 * @warn 只能在createView後使用
	 * @param position - data在列表中的位置
	 * @param data - 傳入的數據
	 */
	public void setView(int position, T data) {
		this.position = position;
		setView(data);
	}
	/**設置並顯示內容
	 * @warn 只能在createView後使用
	 * @param data - 傳入的數據
	 */
	public abstract void setView(T data);

	/**獲取可見性
	 * @warn 只能在createView後使用
	 * @return 可見性 (View.VISIBLE, View.GONE, View.INVISIBLE);
	 */
	public int getVisibility() {
		return convertView.getVisibility();
	}
	/**設置可見性
	 * @warn 只能在createView後使用
	 * @param visibility - 可見性 (View.VISIBLE, View.GONE, View.INVISIBLE);
	 */
	public void setVisibility(int visibility) {
		convertView.setVisibility(visibility);
	}


	/**設置背景
	 * @warn 只能在createView後使用
	 * @param resId
	 */
	public void setBackground(int resId) {
		if (resId > 0 && convertView != null) {
			try {
				convertView.setBackgroundResource(resId);
			} catch (Exception e) {
				Log.e(TAG, "setBackground   try { convertView.setBackgroundResource(resId);" +
						" \n >> } catch (Exception e) { \n" + e.getMessage());
			}
		}
	}


	//resources方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
	public String getString(int id) {
		return resources.getString(id);
	}
	public int getColor(int id) {
		return resources.getColor(id);
	}
	public Drawable getDrawable(int id) {
		return resources.getDrawable(id);
	}
	public float getDimension(int id) {
		return resources.getDimension(id);
	}
	//resources方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


	//show short toast 方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
	/**快捷顯示short toast方法,需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以這個類裏不寫
	 * @param stringResId
	 */
	public void showShortToast(int stringResId) {
		CommonUtil.showShortToast(context, stringResId);
	}
	/**快捷顯示short toast方法,需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以這個類裏不寫
	 * @param string
	 */
	public void showShortToast(String string) {
		CommonUtil.showShortToast(context, string);
	}
	//show short toast 方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


	//啓動新Activity方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

	/**打開新的Activity,向左滑入效果
	 * @param intent
	 */
	public void toActivity(final Intent intent) {
		CommonUtil.toActivity(context, intent);
	}
	/**打開新的Activity
	 * @param intent
	 * @param showAnimation
	 */
	public void toActivity(final Intent intent, final boolean showAnimation) {
		CommonUtil.toActivity(context, intent, showAnimation);
	}
	/**打開新的Activity,向左滑入效果
	 * @param intent
	 * @param requestCode
	 */
	public void toActivity(final Intent intent, final int requestCode) {
		CommonUtil.toActivity(context, intent, requestCode);
	}
	/**打開新的Activity
	 * @param intent
	 * @param requestCode
	 * @param showAnimation
	 */
	public void toActivity(final Intent intent, final int requestCode, final boolean showAnimation) {
		CommonUtil.toActivity(context, intent, requestCode, showAnimation);
	}
	//啓動新Activity方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

	/**銷燬並回收內存,建議在對應的View佔用大量內存時使用
	 * @warn 只能在UI線程中調用
	 */
	public void onDestroy() {
		if (convertView != null) {
			try {
				convertView.destroyDrawingCache();
			} catch (Exception e) {
				Log.w(TAG, "onDestroy  try { convertView.destroyDrawingCache();" +
						" >> } catch (Exception e) {\n" + e.getMessage());
			}
			convertView = null;
		}
		
		onDataChangedListener = null;
		onTouchListener = null;
		onClickListener = null;
		onLongClickListener = null;
		
		data = null;
		position = 0;
		
		context = null;
	}

}

 

 

本示例工程QuickAdapter

下載地址

http://files.cnblogs.com/files/tommylemon/QuickAdapter.zip

下載試用

QuickAdapter.apk

 

用到的開源庫ZBLibrary(歡迎Star,歡迎Fork)

 

下載地址(歡迎Star,歡迎Fork)

https://github.com/TommyLemon/Android-ZBLibrary

下載試用

ZBLibraryDemoApp.apk

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章