打造万能适配器 (80行-25行代码)极限优化

极限.jpg

android中像是ListView和girdview 这种组件在项目中使用频率非常高, adapter 也是每次必写的玩意 合理的封装 优化 可以使得我们的写更少的代码 做更多的事情.

以下文章阐述了如何从80行代码 优化到 25行

ViewHolder 优化

传统的ViewHolder 一般都在自定义的adapter去编写,并且每一个adapter都会对应一个自定义的内部类viewholder.

MyAdapter 中 viewHolder 部分代码:
<pre>
private class ViewHolder{

    TextView  userName;
    TextView  userAge;
    TextView  userAddress;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    ViewHolder holder;
    if(convertView == null){
        convertView = mInflater.inflate(this.layout,parent,false);
        holder = new ViewHolder();

        holder.userName = (TextView) convertView.findViewById(R.id.user_name);
        holder.userAge = (TextView) convertView.findViewById(R.id.user_age);
        holder.userAddress = (TextView) convertView.findViewById(R.id.user_address);

        convertView.setTag(holder);
    }
    else{
        holder = (ViewHolder) convertView.getTag();
    }

    return convertView;
}

</pre>

优化方案 : 将各零散 viewHolder 抽象成一个通用类 适配所有自定义的adapter 并且viewHolder的相关业务 从adapter中 放到 通用viewHolder中.

抽象之后 使用通用viewHolder <b>1</b>行代码
<pre>

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = ViewHolder.get(context, convertView, parent, position, layout);
return viewHolder.getConvertView();
}

</pre>

获得控件我们就可以用通用类中封装好的方法getView(int id)
<pre>
TextView textView = viewHolder.getView(R.id.user_name);
</pre>

以下 ViewHolder 公共类 :
<pre>
/**

  • 抽象公共的viewholder

  • Created by sherlock on 15/12/17.
    */
    public class ViewHolder {

    private SparseArray<View> mViews;
    private int mPosition;
    private View mConvertView;

    public ViewHolder(Context context, ViewGroup parent, int layoutId, int position) {
    this.mPosition = position;
    this.mViews = new SparseArray<>();
    this.mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);

     mConvertView.setTag(this);
    

    }

    /**

    • 获取viewholder
    • @param context
    • @param converView
    • @param parent
    • @param position
    • @param layoutId
    • @return
      */
      public static ViewHolder get(Context context, View converView, ViewGroup parent, int position, int layoutId) {
      if (converView == null) {
      return new ViewHolder(context, parent, layoutId, position);
      } else {
      ViewHolder holder = (ViewHolder) converView.getTag();
      //viewholderr会被复用 及时更新下position
      holder.mPosition = position;
      return holder;
      }
      }
/**
 * 取得viewholder存储的的控件
 * @param viewId
 * @param <T>
 * @return
 */
public <T extends View> T getView(int viewId) {
    View view = mViews.get(viewId);
    if(view == null){
        view = mConvertView.findViewById(viewId);
        mViews.put(viewId,view);
    }

    return (T) view;
}


public View getConvertView() {
    return mConvertView;
}

}

</pre>

Adapter优化

我们建立一个CommonAdapter 继承自BaseAdapter

<pre>

public abstract class CommonAdapter<T> extends BaseAdapter {

protected LayoutInflater mInflater;
protected int layout;
protected Context context;
protected List<T> dataList;

public CommonAdapter(Context context, int layout, List<T> dataList) {
    this.context = context;
    this.layout = layout;
    this.dataList = dataList;
    this.mInflater.from(context);
}

@Override
public int getCount() {
    return dataList.size();
}

@Override
public T getItem(int position) {
    return dataList.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public abstract  View  getView(int position, View convertView, ViewGroup parent);

}

</pre>

使用commonAdapter,代码是不是精简很多 我们还可以继续优化:
<pre>
public class MyAdapter extends CommonAdapter<User> {

public MyAdapter(Context context, int layout,List<User> dataList) {
    super(context,layout,dataList);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder viewHolder = ViewHolder.get(context, convertView, parent, position, layout);
    //使用
    TextView textView = viewHolder.getView(R.id.user_name);
    return viewHolder.getConvertView();
}

}

</pre>

我可以做到让使用者更加专注他们的业务, 可以将
ViewHolder viewHolder = ViewHolder.get(context, convertView, parent, position, layout);
return viewHolder.getConvertView();
两部分代码 继续封装 复用

在CommonAdapter中加入 一个抽象方法
public abstract void convert(ViewHolder holder,T t);
在commonAdapter中实现getView
<pre>

@Override
public View getView(int position, View convertView, ViewGroup parent){
ViewHolder viewHolder = ViewHolder.get(context, convertView, parent, position, layout);
convert(viewHolder,getItem(position));
return viewHolder.getConvertView();
}
</pre>

我们的MyAdapter来实现convert 这个部分就是暴露给 使用者的部分 在这里可以拿到一个holde如和 对应业务bean的俩个对象 让你专注填业务

超级清爽
<pre>
public class MyAdapter extends CommonAdapter<User> {

public MyAdapter(Context context, int layout,List<User> dataList) {
    super(context,layout,dataList);
}

@Override
public void convert(ViewHolder holder, User user) {
    //使用
    TextView textView = holder.getView(R.id.user_name);
    textView.setText(user.getUserName());
}

}
</pre>

极限优化 1行代码

我们可以通过链式调用来实现这个效果,我们在ViewHolder中 写2个辅助方法

<pre>
public ViewHolder setText(int viewId,String text){
TextView textView = getView(viewId);
textView.setText(text);
return this;
}

public ViewHolder setImageResource(int viewId,int resId){
ImageView imageView = getView(viewId);
imageView.setImageResource(resId);
return this;
}
</pre>

可以根据你的控件情况 来封装不同的方法.

使用起来很easy了 呵呵 真的一行足矣
<pre>

public class MyAdapter extends CommonAdapter<User> {

public MyAdapter(Context context, int layout, List<User> dataList) {
    super(context, layout, dataList);
}

@Override
public void convert(ViewHolder holder, User user) {
    holder  .setText(R.id.user_name, user.getUserName())
            .setText(R.id.user_age, user.getUserAge())
            .setText(R.id.user_address, user.getUserAddress());

}

}
</pre>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容