你的位置:首页 > 操作系统

[操作系统]高灵活低耦合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       @Override103       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没有提供的 方法。

 1 package zuo.biao.library.base; 2  3 import zuo.biao.library.util.CommonUtil; 4 import zuo.biao.library.util.Log; 5 import android.app.Activity; 6 import android.content.Intent; 7 import android.content.res.Resources; 8 import android.graphics.drawable.Drawable; 9 import android.support.annotation.NonNull; 10 import android.view.LayoutInflater; 11 import android.view.View; 12 import android.view.View.OnClickListener; 13 import android.view.View.OnLongClickListener; 14 import android.view.View.OnTouchListener; 15  16 /**基础自定义View 17  * @author Lemon 18  * @param <T> 数据模型(model/JavaBean)类 19  * @see #onDestroy 20  * @use extends BaseView<T>, 具体参考.DemoView 21 */ 22 public abstract class BaseView<T> { 23   private static final String TAG = "BaseView"; 24  25   /** 26    * 传入的Activity,可在子类直接使用 27   */ 28   protected Activity context; 29   protected Resources resources; 30   public BaseView(Activity context, Resources resources) { 31     this.context = context; 32     this.resources = resources == null ? context.getResources() : resources; 33   } 34  35   /**数据改变回调接口 36    * (Object) getData() - 改变的数据 37   */ 38   public interface OnDataChangedListener { 39     void onDataChanged(); 40   } 41  42   public OnDataChangedListener onDataChangedListener;//数据改变回调监听类的实例 43   /**设置数据改变事件监听类 44    * @param l 45   */ 46   public void setOnDataChangedListener(OnDataChangedListener l) { 47     onDataChangedListener = l; 48   } 49  50   public OnTouchListener onTouchListener;//接触View回调监听类的实例 51   /**设置接触View事件监听类 52    * @param l 53   */ 54   public void setOnTouchListener(OnTouchListener l) { 55     onTouchListener = l; 56   } 57  58   public OnClickListener onClickListener;//点击View回调监听类的实例 59   /**设置点击View事件监听类 60    * @param l 61   */ 62   public void setOnClickListener(OnClickListener l) { 63     onClickListener = l; 64   } 65  66   public OnLongClickListener onLongClickListener;//长按View回调监听类的实例 67   /**设置长按View事件监听类 68    * @param l 69   */ 70   public void setOnLongClickListener(OnLongClickListener l) { 71     onLongClickListener = l; 72   } 73  74  75  76   /** 77    * 子类整个视图,可在子类直接使用 78    * @must createView方法内对其赋值且不能为null 79   */ 80   protected View convertView = null; 81  82   /**通过id查找并获取控件,使用时不需要强转 83    * @param id 84    * @return  85   */ 86   @SuppressWarnings("unchecked") 87   public <V extends View> V findViewById(int id) { 88     return (V) convertView.findViewById(id); 89   } 90   /**通过id查找并获取控件,并setOnClickListener 91    * @param id 92    * @param l 93    * @return 94   */ 95   public <V extends View> V findViewById(int id, OnClickListener l) { 96     V v = findViewById(id); 97     v.setOnClickListener(l); 98     return v; 99   }100   /**创建一个新的View101    * @return102   */103   public abstract View createView(@NonNull LayoutInflater inflater);104 105   /**获取convertView的宽度106    * @warn 只能在createView后使用107    * @return108   */109   public int getWidth() {110     return convertView.getWidth();111   }112   /**获取convertView的高度113    * @warn 只能在createView后使用114    * @return115   */116   public int getHeight() {117     return convertView.getHeight();118   }119 120   /**121    * data在列表中的位置122    * @must 只使用setView(int position, T data)方法来设置position,保证position与data对应正确123   */124   protected int position = 0;125   /**获取data在列表中的位置126   */127   public int getPosition() {128     return position;129   }130 131   protected T data = null;132   /**获取数据133    * @return134   */135   public T getData() {136     return data;137   }138 139   /**设置并显示内容140    * @warn 只能在createView后使用141    * @param position - data在列表中的位置142    * @param data - 传入的数据143   */144   public void setView(int position, T data) {145     this.position = position;146     setView(data);147   }148   /**设置并显示内容149    * @warn 只能在createView后使用150    * @param data - 传入的数据151   */152   public abstract void setView(T data);153 154   /**获取可见性155    * @warn 只能在createView后使用156    * @return 可见性 (View.VISIBLE, View.GONE, View.INVISIBLE);157   */158   public int getVisibility() {159     return convertView.getVisibility();160   }161   /**设置可见性162    * @warn 只能在createView后使用163    * @param visibility - 可见性 (View.VISIBLE, View.GONE, View.INVISIBLE);164   */165   public void setVisibility(int visibility) {166     convertView.setVisibility(visibility);167   }168 169 170   /**设置背景171    * @warn 只能在createView后使用172    * @param resId173   */174   public void setBackground(int resId) {175     if (resId > 0 && convertView != null) {176       try {177         convertView.setBackgroundResource(resId);178       } catch (Exception e) {179         Log.e(TAG, "setBackground  try { convertView.setBackgroundResource(resId);" +180             " \n >> } catch (Exception e) { \n" + e.getMessage());181       }182     }183   }184 185 186   //resources方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<187   public String getString(int id) {188     return resources.getString(id);189   }190   public int getColor(int id) {191     return resources.getColor(id);192   }193   public Drawable getDrawable(int id) {194     return resources.getDrawable(id);195   }196   public float getDimension(int id) {197     return resources.getDimension(id);198   }199   //resources方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>200 201 202   //show short toast 方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<203   /**快捷显示short toast方法,需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以这个类里不写204    * @param stringResId205   */206   public void showShortToast(int stringResId) {207     CommonUtil.showShortToast(context, stringResId);208   }209   /**快捷显示short toast方法,需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以这个类里不写210    * @param string211   */212   public void showShortToast(String string) {213     CommonUtil.showShortToast(context, string);214   }215   //show short toast 方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>216 217 218   //启动新Activity方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<219 220   /**打开新的Activity,向左滑入效果221    * @param intent222   */223   public void toActivity(final Intent intent) {224     CommonUtil.toActivity(context, intent);225   }226   /**打开新的Activity227    * @param intent228    * @param showAnimation229   */230   public void toActivity(final Intent intent, final boolean showAnimation) {231     CommonUtil.toActivity(context, intent, showAnimation);232   }233   /**打开新的Activity,向左滑入效果234    * @param intent235    * @param requestCode236   */237   public void toActivity(final Intent intent, final int requestCode) {238     CommonUtil.toActivity(context, intent, requestCode);239   }240   /**打开新的Activity241    * @param intent242    * @param requestCode243    * @param showAnimation244   */245   public void toActivity(final Intent intent, final int requestCode, final boolean showAnimation) {246     CommonUtil.toActivity(context, intent, requestCode, showAnimation);247   }248   //启动新Activity方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>249 250   /**销毁并回收内存,建议在对应的View占用大量内存时使用251    * @warn 只能在UI线程中调用252   */253   public void onDestroy() {254     if (convertView != null) {255       try {256         convertView.destroyDrawingCache();257       } catch (Exception e) {258         Log.w(TAG, "onDestroy try { convertView.destroyDrawingCache();" +259             " >> } catch (Exception e) {\n" + e.getMessage());260       }261       convertView = null;262     }263     264     onDataChangedListener = null;265     onTouchListener = null;266     onClickListener = null;267     onLongClickListener = null;268     269     data = null;270     position = 0;271     272     context = null;273   }274 275 }

 

 

本示例工程QuickAdapter

下载地址

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

下载试用

QuickAdapter.apk

 

用到的开源库ZBLibrary(欢迎Star,欢迎Fork)

 

下载地址

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

下载试用

ZBLibraryDemoApp.apk