Android DataBinding使用总结(三)列表展示

前言

在我的前两篇文章中,简单学习了以下内容:

Android DataBinding使用总结 (一) DataBinding的环境配置和基本使用

Android DataBinding使用总结(二) Databinding的所有基本使用方法

本文将进行阐述如何通过DataBinding展示RecyclerView列表

先看一下效果:

这里写图片描述

1.每个item展示Student name 和Student age两个Button

2.点击name时,触发点击事件

3.点击age时,触发点击事件,同时修改该控件的paddingLeft值

一、Activity代码

1.activity:先大概看一遍,不需要都看懂,我们后面会讲
public class RecyclerBindActivity extends AppCompatActivity {

    private ActivityRecyclerBindBinding binding;

    private RecyclerView recyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bind();
    }

    private void bind() {
        binding = DataBindingUtil.setContentView(this, R.layout.activity_recycler_bind);

        ArrayList<Student> students = getStudents();

       SimpleBindAdapter adapter = new SimpleBindAdapter(students, R.layout.item_recycler_view);
        adapter.setItemPresenter(new RecyclerBindPresenter());
        binding.recyclerView
                .setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        binding.recyclerView
                .setAdapter(adapter);
    }

    //presenter控制点击事件
    public class RecyclerBindPresenter implements IBaseBindingPresenter {

        public void onNameClick(Student student) {
            Toast.makeText(RecyclerBindActivity.this, student.name.get() + "要改名字", Toast.LENGTH_SHORT).show();
            student.name.set("我改名字啦!");
        }

        /**
         * 点击用户年龄 += 3,且空间的左内边距+=3;
         * {@link com.mei_husky.samplemvvm.view.bind.BindingUtil}
         */
        public void onAgeClick(Student student) {
            Toast.makeText(RecyclerBindActivity.this, String.valueOf("涨了三岁"), Toast.LENGTH_SHORT).show();
            student.setAge(student.getAge()+3);
        }
    }


    private ArrayList<Student> getStudents() {
        ArrayList<Student> students = new ArrayList<>();
        students.add(new Student("jack", 12));
        students.add(new Student("rose", 13));
        students.add(new Student("qingmei2", 18));
        students.add(new Student("unknown", 21));
        return students;
    }
}
2.layout代码:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </LinearLayout>
</layout>

二、奇怪的Adapter

我们来看看Adapter代码:

public class SimpleBindAdapter extends BaseBindingAdapter<Student, ItemRecyclerViewBinding> {

    public SimpleBindAdapter(List<Student> mDatas, int layoutId) {
        super(mDatas, layoutId);
    }

    /**
     * 如果有特殊需求可以实现在该方法中
     * @param holder
     */
    @Override
    public void onCreateViewHolder(BaseViewHolder<ItemRecyclerViewBinding> holder) {

    }
}

是不是很难理解!

Adapter怎么长成这样了?ViewHolder呢?

事实上这就是DataBinding Magic的地方,我们首先要知道ViewHolder的意义:用来处理数据和控件的交互,也就是说把数据放在控件上面,控件被点击之后我们再处理控件的点击事件,即:

数据 -> 控件
控件 -> 数据

而DataBinding能够实现的就是数据和控件的数据绑定,所以我们只要略微做出处理,就能够通过了了几行代码实现列表!实际上,大部分的列表需求都不需要额外的Adapter和ViewHolder!

我们如何才能基本抛弃Adapter和ViewHolder实现列表呢,或者说我们需要什么才能展示列表:

1、数据源Datas

我们当然需要数据源,这是我们需要去展示的,展示在item_layout上去

2、item的layoutId

我们知道了layoutId,就能通过DataBinding进行数据绑定。

3、UI调度器(Adapter和ViewHolder)

显然我们并不是太需要他们了,待会我们会实现一个BaseAdapter和BaseViewHolder,从而一次创建,之后到处使用就可以啦

4、点击事件处理器Presenter

细心的读者能发现,我们已经放在了Activity中的Presenter去处理所有的点击事件了,我们将点击事件的所有处理全部放在Presenter中,然后调用adapter.setItemPresenter()将响应事件传入即可。

三、强撸一波代码

0.item_layout:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="itemPresenter"
            type="com.mei_husky.samplemvvm.view.activity.RecyclerBindActivity.RecyclerBindPresenter" />

        <variable
            name="data"
            type="com.mei_husky.samplemvvm.model.Student" />

    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:background="#ff0"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAllCaps="false"
            android:layout_margin="16dp"
            android:gravity="center_vertical"
            android:onClick="@{() -> itemPresenter.onNameClick(data)}"
            android:text="@{`Student Name : `+ data.name.get()}" />

        <!--显示年龄,点击年龄+3,同时paddingleft也绑定年龄-->
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="16dp"
            android:textAllCaps="false"
            android:gravity="center_vertical"
            android:onClick="@{() -> itemPresenter.onAgeClick(data)}"
            android:paddingLeft="@{data.age}"
            android:text="@{`Student Age : `+data.age}" />

    </LinearLayout>
</layout>
1.BaseBindingAdapter
public abstract class BaseBindingAdapter<T, D extends ViewDataBinding> extends RecyclerView.Adapter<BaseViewHolder<D>> {

    private List<T> mDatas;
    private int layoutId;

    //用于设置Item的事件Presenter
    protected IBaseBindingPresenter ItemPresenter;

    public BaseBindingAdapter(List<T> mDatas, int layoutId) {
        this.mDatas = mDatas;
        this.layoutId = layoutId;
    }

    @Override
    public BaseViewHolder<D> onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        BaseViewHolder<D> viewHolder = new BaseViewHolder<D>((D) DataBindingUtil.inflate(inflater, layoutId, parent, false));
        onCreateViewHolder(viewHolder);
        return viewHolder;
    }

    public abstract void onCreateViewHolder(BaseViewHolder<D> holder);

    @Override
    public void onBindViewHolder(BaseViewHolder<D> holder, int position) {
        Log.i("tag", "onBindViewHolder");
        holder.getBinding().setVariable(BR.data, mDatas.get(position));
        holder.getBinding().setVariable(BR.itemPresenter, ItemPresenter);
        holder.getBinding().executePendingBindings();
    }

    @Override
    public int getItemCount() {
        return mDatas == null ? 0 : mDatas.size();
    }

    /**
     * 用于设置Item的事件Presenter
     *
     * @param itemPresenter
     * @return
     */
    public BaseBindingAdapter setItemPresenter(IBaseBindingPresenter itemPresenter) {
        ItemPresenter = itemPresenter;
        return this;
    }

}
2、点击事件处理接口:
public interface IBaseBindingPresenter {

}
3、BaseViewHolder:
public class BaseViewHolder<T extends ViewDataBinding> extends RecyclerView.ViewHolder {

    protected final T binding;

    public BaseViewHolder(T t) {
        super(t.getRoot());
        this.binding = t;
    }

    public T getBinding() {
        return binding;
    }

}
4.在Activity中展示列表:
public class RecyclerBindActivity extends AppCompatActivity {

    private ActivityRecyclerBindBinding binding;

    private RecyclerView recyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bind();
    }

    private void bind() {
        binding = DataBindingUtil.setContentView(this, R.layout.activity_recycler_bind);

        ArrayList<Student> students = getStudents();

        SimpleBindAdapter adapter = new SimpleBindAdapter(students, R.layout.item_recycler_view);
        adapter.setItemPresenter(new RecyclerBindPresenter());
        binding.recyclerView
                .setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        binding.recyclerView
                .setAdapter(adapter);
    }

    //presenter控制点击事件
    public class RecyclerBindPresenter implements IBaseBindingPresenter {

        public void onNameClick(Student student) {
            Toast.makeText(RecyclerBindActivity.this, student.name.get() + "要改名字", Toast.LENGTH_SHORT).show();
            student.name.set("我改名字啦!");
        }

        /**
         * 点击用户年龄 += 3,且空间的左内边距+=3;
         * {@link com.mei_husky.samplemvvm.view.bind.BindingUtil}
         */
        public void onAgeClick(Student student) {
            Toast.makeText(RecyclerBindActivity.this, String.valueOf("涨了三岁"), Toast.LENGTH_SHORT).show();
            student.setAge(student.getAge()+3);
        }
    }


    private ArrayList<Student> getStudents() {
        ArrayList<Student> students = new ArrayList<>();
        students.add(new Student("jack", 12));
        students.add(new Student("rose", 13));
        students.add(new Student("qingmei2", 18));
        students.add(new Student("unknown", 21));
        return students;
    }
}
5.创建BindUtil,处理点击age,paddingLeft+3的逻辑:

自定义 Setters
一些属性需要自定义绑定逻辑,android:paddingLeft 属性并没有对应的setter方法,但是存在setPadding(left, top, right, bottom)方法。通过 BindingAdapter 注释来自定义属性调用的静态setter方法。android 系统已经创建了 BindingAdapter 函数,下面是 paddingLeft 属性对应的函数:

public class BindingUtil {

    /**
     * 该效果展示在->MainActivity ->Databinding展示列表 -> 点击item的Age按钮
     * {@link com.mei_husky.samplemvvm.view.activity.RecyclerBindActivity}
     *
     * @param view
     * @param padding
     */
    @BindingAdapter("android:paddingLeft")
    public static void setPaddingLeft(View view, int padding) {
        view.setPadding(padding,
                view.getPaddingTop(),
                view.getPaddingRight(),
                view.getPaddingBottom());
    }
}

该注解的详情,请看文末谷歌官方文档:

https://developer.android.com/topic/libraries/data-binding/index.html

到此,列表展示,需求实现。

总结

总结一下实现方式:

1.我们创建BaseViewHolder和BaseAdapter(之后这步就可以直接跳过)

2.绘制xml布局文件,variable导入datas数据和presenter响应事件

3.实现IBaseBindingPresenter接口自定义响应事件

4.activity中代码使用

其实看着可能有点头晕,但是敲一遍就能明白了,其实代码中还有一点需要优化的,就是并没有直接的方式在xml中给recyclerView设置Adapter和LayoutManager:

 <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        app:adapter = "@{presenter.adapter}"  //like this
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

但其实依赖上文中的@BindingAdapter注解,实现起来也是非常简单,不赘述

我的其它文章:

Android DataBinding使用总结(四)多类型列表展示

Android MVVM+DataBinding结合Dagger2进行开发

Android 神兵利器Dagger2使用详解(一)基础使用

参考文档:

DataBinding 谷歌官方文档
没有翻墙的用户可以看这篇:
Data Binding Guide——google官方文档翻译

本文中所有代码都已托管在GitHub上面:

Github传送门,点我查看源码

该demo包含本文中所有代码但不仅限于:

使用了 Mvvm+DataBinding 搭建的DemoApp

1.MainActivity

-DataBinding的入门使用以及引导界面

2.DataBindingBaseActivity

-Databinding的所有基本使用方法

3.RecyclerBindActivity

-RecyclerView中使用dataBinding进行列表展示

4.MulTypeRecyclerBindActivity

-RecyclerView中使用dataBinding展示多类型列表

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值