高灵活低耦合Adapter快速开发攻略

Posted 孤独的探索号-Android&Java开发者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高灵活低耦合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)

 

下载地址

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

下载试用

ZBLibraryDemoApp.apk

 

 

 

以上是关于高灵活低耦合Adapter快速开发攻略的主要内容,如果未能解决你的问题,请参考以下文章

设计模式浅谈——抽象和解耦

浅谈面向对象开发原则:高内聚,低耦合

低耦合,高内聚。实乃至理名言

让你快速搞定各服务端(api,pc,mobile,wechat)代码的框架

阅码场直播 - 《论高内聚和低耦合》

浅谈高内聚低耦合