美文网首页Android进阶Android开发程序员
Android Databinding对adapter(Recy

Android Databinding对adapter(Recy

作者: 闲庭 | 来源:发表于2017-10-18 20:32 被阅读114次

    作为一个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);

    相关文章

      网友评论

        本文标题:Android Databinding对adapter(Recy

        本文链接:https://www.haomeiwen.com/subject/jgaoyxtx.html