Android Databinding对adapter(RecyclerView)适配器基类封装

作为一个android 开发者,心里似乎对RecyclerView又爱又恨,爱的是它对列表数据处理功能够强大,恨得是要写adapter 和 viewholder ,虽然说写adapter 和 viewholder倒不是难,而是烦,千遍一率的相似代码,对于程序员来说,重复是最令人讨厌的。所以这才有这么多仁人志士,前俯后继地进行通用型,万能型 adapter 的抽象。即便已经有好多的通用性、万能型adapter适配器,但是我在这里还是要讲下Databinding对adapter(RecyclerView)适配器基类封装。

DataBinding的核心理念是数据驱动。数据驱动驱动的目标就是View,使用DataBinding,我们通过添加、修改、删除数据源,View就会自动予以相关变化,达到一种双向绑定的效果。也就是说Databinding出现的意义就在于系统自动帮助我们生成Data和View之间的connection.而在Adapter中出现的ViewHolder就是我们手动生成的connection,下面我们就来看看databinding如何精简对应的adapter。

  1. 下面先看看一个简单的RecyclerView Adapter代码:
public class UserAdapter extends RecyclerView.Adapter
    {
        @Override
        public int getItemCount()
        {
            return 0;
        }
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
        {
            return null;
        }
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
        {
    
        }
    }
  • 通过getItemsCount(), RecyclerView知道了所有子项的数量。

  • 通过onCreateViewHolder(), RecyclerView知道了每一个子项长什么样子。

  • 通过onBindViewHolder(),让每个子项得以显示正确的数据。

可以看到,Adapter起的作用和DataBinding是非常类似的,使用DataBinding,可以使Adapter的编写显得更加简单。

  1. 下面看看使用DataBinding编写的adapter:

adapter基础类:

public abstract class RecyclerAdapter<T, B extends ViewDataBinding> extends RecyclerView.Adapter {

    protected Context mContext;
    protected List<T> mList;

    public RecyclerAdapter(Context context) {
        this.mContext = context;
    }

    public RecyclerAdapter(Context context, List<T> list) {
        this.mContext = context;
        this.mList = list;
    }
    @Override
    public int getItemCount() {
        return mList == null ? 0 : mList.size();
    }

    public void refreshData(List<T> list){
        if (mList == null){
            mList = new ArrayList<>();
        }
        mList.addAll(list);
        notifyDataSetChanged();
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        B bing = DataBindingUtil.inflate(LayoutInflater.from(mContext), getLayoutResId(viewType), parent, false);
        return new RecyclerHolder(bing.getRoot());
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        B binding = DataBindingUtil.getBinding(holder.itemView);
        final T t = mList.get(position);
        onBindItem(binding, t, position);
    }

    protected abstract @LayoutRes int getLayoutResId(int viewType);

    protected abstract void onBindItem(B binding, T t, int position);

    static class RecyclerHolder extends RecyclerView.ViewHolder {

        public RecyclerHolder(View itemView) {
            super(itemView);
        }
    }

}
  • 通过getLayoutResId我们告诉了RecyclerView子项长什么样子。

  • 通过onBindItem我们给具体的每个子项绑定了合适的数据。
    至于具体的绑定过程,是放在布局的xml文件中的。

后续RecyclerView的adapter继承基类即可:

public class UserAdapter extends RecyclerAdapter<User,ItemUserBinding>{
    public TakePhotoAdapter(Activity context) {
        super(context);
    }

    @Override
    protected int getLayoutResId(int viewType) {
        return R.layout.item_user;
    }

    @Override
    protected void onBindItem(final ItemUserBinding binding,
                              final User user,
                              final int position) {
        binding.setUserInfo(user);
        binding.executePendingBindings();
        binding.ivTakePhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ToastUitl.showShort("点击了"+user.getName()+position);
            }
        });
    }
}

此处处理item的一些click事件或者其他事件直接写到adapter里面去,但是考虑到adapter还是比较纯粹的处理view和data的关系,所以把事件的处理通过接口回调到activity层。代码如下:

@FunctionalInterface
public interface BindingItemListen<T, B extends ViewDataBinding> {
    void onItemClick(B binding, T t, int i);
}



public class UserAdapter extends RecyclerAdapter<User,ItemUserBinding>{
    private BindingItemListen  itemListen;
    public TakePhotoAdapter(Activity context,
            BindingItemListen<User,ItemUserBinding> itemListen) {
        super(context);
        this.itemListen = itemListen;
    }

    @Override
    protected int getLayoutResId(int viewType) {
        return R.layout.item_user;
    }

    @Override
    protected void onBindItem(final ItemUserBinding binding,
                              final User user,
                              final int position) {
        binding.setUserInfo(user);
        binding.executePendingBindings();
        binding.ivTakePhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ToastUitl.showShort("点击了"+user.getName()+position);
                itemListen.onItemClick(binding,user,position);
            }
        });
    }
}

此时在activity中的应用:

recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new UserAdapter(this, new BindingItemListen<User, ItemUserBinding>() {
    @Override
    public void onItemClick(ItemUserBinding binding, User user, int i) {

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

推荐阅读更多精彩内容