Android DataBinding使用总结(五)结合MultiType展示多类型列表
来源:互联网 发布:直播软件商业计划书 编辑:程序博客网 时间:2024/05/20 18:51
前言
在我的前几篇文章中,简单学习了以下内容:
Android DataBinding使用总结 (一) DataBinding的环境配置和基本使用
Android DataBinding使用总结(二) DataBinding的所有基本使用方法
Android DataBinding使用总结(三) DataBinding展示RecyclerView列表
Android DataBinding使用总结(四) DataBinding的多类型列表展示
我们在上文中通过自己动手实现BaseMulTypeAdapter类,从而达到了一次实现,多次复用的效果,大概流程为:
1.创建不同类型item的xml布局文件
2.使对应的数据类(javaBean)实现IMulTypeBindingBean接口,在接口中返回该数据对应item类型的布局ID;
3.创建BaseViewHolder和BaseMulTypeAdapter,之后我们在实现列表时,再也不需要实现Adapter和ViewHolder,只需要复用即可
4.Activity中初始化RecyclerView,设置Adapter和LayoutManager
今天主要是学习一下如何展示通过另外一种方式实现RecyclerView多类型列表,效果如下:(为了方便,不同的item采取不同的背景颜色)
一、MultiType库简介
drakeet/MultiType(点我查看Github源码),是GitHub上开源的实现多类型列表的一个第三方库,中文文档如下:
中文说明文档
使用方式如下:
Step 1
创建一个 class,它将是你的数据类型或 Java bean / model. 对这个类的内容没有任何限制。示例如下:
public class Category { @NonNull public final String text; public Category(@NonNull String text) { this.text = text; }}
Step 2
创建一个 class 继承 ItemViewBinder.
ItemViewBinder 是个抽象类,其中 onCreateViewHolder 方法用于生产你的 Item View Holder, onBindViewHolder 用于绑定数据到 Views. 一般一个 ItemViewBinder 类在内存中只会有一个实例对象,MultiType 内部将复用这个 binder 对象来生产所有相关的 item views 和绑定数据。示例:
public class CategoryViewBinder extends ItemViewBinder<Category, CategoryViewBinder.ViewHolder> { @NonNull @Override protected ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) { View root = inflater.inflate(R.layout.item_category, parent, false); return new ViewHolder(root); } @Override protected void onBindViewHolder(@NonNull ViewHolder holder, @NonNull Category category) { holder.category.setText(category.text); } static class ViewHolder extends RecyclerView.ViewHolder { @NonNull private final TextView category; ViewHolder(@NonNull View itemView) { super(itemView); this.category = (TextView) itemView.findViewById(R.id.category); } }}
Step 3
在 Activity 中加入 RecyclerView 和 List 并注册你的类型,示例:
public class MainActivity extends AppCompatActivity { private MultiTypeAdapter adapter; /* Items 等同于 ArrayList<Object> */ private Items items; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list); adapter = new MultiTypeAdapter(); /* 注册类型和 View 的对应关系 */ adapter.register(Category.class, new CategoryViewBinder()); adapter.register(Song.class, new SongViewBinder()); recyclerView.setAdapter(adapter); /* 模拟加载数据,也可以稍后再加载,然后使用 * adapter.notifyDataSetChanged() 刷新列表 */ items = new Items(); for (int i = 0; i < 20; i++) { items.add(new Category("Songs")); items.add(new Song("小艾大人", R.drawable.avatar_dakeet)); items.add(new Song("许岑", R.drawable.avatar_cen)); } adapter.setItems(items); adapter.notifyDataSetChanged(); }}
大功告成!这就是 MultiType 的基础用法了。其中 onCreateViewHolder 和 onBindViewHolder 方法名沿袭了使用 RecyclerView 的习惯,令人一目了然,减少了新人的学习成本。
上述为作者为我们提供普通方式实现多类型列表的步骤,接下来我们通过DataBinding结合作者的MultiType库进行多类型列表的实现。
二、转折
在学习之前,会不会有这样一种想法:
我为什么要学习这个库?
可以理解,我们可能已经学习了很多种RecyclerView实现多类型列表的方式,我们有什么必要去多花费时间成本学习?
——何况我们已经知道如何通过DataBinding进行多类型列表的展示了。
我们先归纳一下RecyclerView多类型列表展示的方法:
1、普通方式实现多类型列表,较简单,好理解;
2、面向接口,实现耦合性极低的多类型列表;
3、DataBinding实现可多次复用的Adapter,从而实现多类型列表
4、其他方式
上述前两种实现方式,可以通过我的 RecyclerView3-面向接口优雅地实现多类型列表
文中进行了解;第三种方式可以通过我的上一篇文章Android DataBinding使用总结(四) DataBinding的多类型列表展示 进行简单了解。
抛开其他不谈,单说DataBinding实现多类型列表,我们从上一篇文中可以得知,我们仅仅需要了了数行代码即可实现多类型列表:
/** * 几行代码展示多类型列表 */ MulTypeBindAdapter adapter = new MulTypeBindAdapter(students); adapter.setItemPresenter(new MulRecyclerBindPresenterI()); binding.recyclerView .setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); binding.recyclerView .setAdapter(adapter);
对于不同的item,我们在Adapter中仅需要传入数据源(数据源中不同类型数据已绑定不同类型的item布局文件),响应事件我们只需要实现Presenter接口并传入即可。
关于这个库,我的理解是「灵活 」。
套用作者的话:
MultiType 设计伊始,我给它定了几个原则:
1、要简单,便于他人阅读代码
因此我极力避免将它复杂化,避免加入许多不相干的内容。我想写人人可读的代码,使用简单的方式,去实现复杂的需求。过多不相干、没必要的代码,将会使项目变得令人晕头转向,难以阅读,遇到需要定制、解决问题的时候,无从下手。
2、要灵活,便于拓展和适应各种需求
很多人会得意地告诉我,他们把 MultiType 源码精简成三四个类,甚至一个类,以为代码越少就是越好,这我不能赞同。MultiType 考虑得更远,这是一个提供给大众使用的类库,过度的精简只会使得大幅失去灵活性。它或许不是使用起来最简单的,但很可能是使用起来最灵活的。 在我看来,”直观”、”灵活”优先级大于”简单”。因此,MultiType 以接口或抽象进行连接,这意味着它的角色、组件都可以被替换,或者被拓展和继承。如果你觉得它使用起来还不够简单,完全可以通过继承封装出更具体符合你使用需求的方法。它已经暴露了足够丰富、周到的接口以供拓展,我们不应该直接去修改源码,这会导致一旦后续发现你的精简版满足不了你的需求时,已经没有回头路了。
3、要直观,使用起来能令项目代码更清晰可读,一目了然
MultiType 提供的 ItemViewBinder 沿袭了 RecyclerView Adapter 的接口命名,使用起来更加舒适,符合习惯。另外,MultiType 很多地方放弃使用反射而是让用户显式指明一些关系,如:MultiTypeAdapter#register 方法,需要传递一个数据模型 class 和 ItemViewBinder 对象,虽然有很多方法可以把它精简成单一参数方法,但我们认为显式声明数据模型类与对应关系,更具直观。
直接通过上文中的方式实现多类型列表,没有任何问题,但是耦合性相对较高,首先,如果我们更改需求,那么我们要修改数据源(JavaBean.class中的IMulTypeBindingBean接口),还需要修改Presenter中对应的回调方法,也就是说,我们除了xml文件,还需要修改至少两个类。
所幸和普通方式实现方式不同,我们至少并不需要修改Adapter和ViewHolder…… 0 0
那么我们通过MultiType这个库实现之后呢,需要修改几个类?
答案是:一个
三、代码
如果你已经亲手实践过这个库,或者了解了这个库的使用方式,那么我们开始吧。
1、数据源(JavaBean)
和上一篇文中不同,我们不需要修改任何东西,或者实现什么接口。
2、xml文件
我们列出两种不同item的xml布局文件:
1、item_multitype_library_view1.xml
<?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.adapter.binder.MultiTypeBinder1.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:layout_margin="16dp" android:gravity="center_vertical" android:textAllCaps="false" android:text="@{`Student Name : `+ data.name.get()}" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="16dp" android:textAllCaps="false" android:gravity="center_vertical" android:text="@{`Student Age : `+data.age}" /> </LinearLayout></layout>
2、item_multitype_library_view2.xml
<?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.adapter.binder.MultiTypeBinder2.RecyclerBindPresenter" /> <variable name="data" type="String" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="80dp" android:orientation="horizontal"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="16dp" android:gravity="center_vertical" android:textAllCaps="false" android:text="@{`String Name : `+ data}" /> </LinearLayout></layout>
3、创建BaseViewHolder
和前两篇文章中一模一样的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、每一个不同类型的item,对应一个ItemViewBinder的子类:
//第一种itempublic class MultiTypeBinder1 extends ItemViewBinder<Student,BaseViewHolder<ItemMultitypeLibraryView1Binding>>{ @NonNull @Override protected BaseViewHolder<ItemMultitypeLibraryView1Binding> onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) { ItemMultitypeLibraryView1Binding binding = DataBindingUtil.inflate(inflater,R.layout.item_multitype_library_view1, parent, false); return new BaseViewHolder(binding); } @Override protected void onBindViewHolder(@NonNull BaseViewHolder<ItemMultitypeLibraryView1Binding> holder, @NonNull Student item) { holder.getBinding().setData(item); holder.getBinding().executePendingBindings(); } //对于不同的响应事件,我们可以这样 public class RecyclerBindPresenter implements IBaseBindingPresenter { public void onNameClick(Student student) { //TODO } }}//第二种itempublic class MultiTypeBinder2 extends ItemViewBinder<String,BaseViewHolder<ItemMultitypeLibraryView2Binding>>{ @NonNull @Override protected BaseViewHolder<ItemMultitypeLibraryView2Binding> onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) { ItemMultitypeLibraryView2Binding binding = DataBindingUtil.inflate(inflater,R.layout.item_multitype_library_view2, parent, false); return new BaseViewHolder(binding); } @Override protected void onBindViewHolder(@NonNull BaseViewHolder<ItemMultitypeLibraryView2Binding> holder, @NonNull String item) { holder.getBinding().setData(item); holder.getBinding().executePendingBindings(); } //对于不同的响应事件,我们可以这样 public class RecyclerBindPresenter implements IBaseBindingPresenter { public void onNameClick(Student student) { //TODO } }}
5、Activity中使用
/** * 展示多类型列表 */ public void showMultiTypeList(){ MultiTypeAdapter adapter = new MultiTypeAdapter(); adapter.register(Student.class,new MultiTypeBinder1()); adapter.register(String.class,new MultiTypeBinder2()); binding.recyclerView.setAdapter(adapter); binding.recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false)); Items items = new Items(); for (int i = 0; i < 10; i++) { items.add(new String("Songs")); items.add(new Student("xiaoming", 29)); items.add(new Student("qingmei2", 18)); } adapter.setItems(items); adapter.notifyDataSetChanged(); }
总结
需求实现,我们可以看到,如果我们有item需求变动,修改的时候只需要找到对应的MultiTypeBinder类修改即可,无论是layout文件或者响应事件,亦或者添加其他需求在onCreateViewHolder()&onBindViewHolder()方法中,拓展性都非常优秀;而且只需要修改这一个类,耦合性更低。
我的下一篇文章将会进行介绍:
Android MVVM+DataBinding结合Dagger2进行开发
参考文档
DataBinding 谷歌官方文档
本文源码地址
Github传送门,点我查看源码
该demo包含本文中所有代码但不仅限于:
使用了 Mvvm+DataBinding 搭建的DemoApp
——DataBinding的入门使用以及引导界面
——Databinding的使用
——RecyclerView中使用dataBinding进行列表展示
——RecyclerView中使用dataBinding展示多类型列表
——MultiType库+DataBinding展示RecyclerView多类型列表
——简单搭建MVVM+DataBinding+Dagger2的界面
- Android DataBinding使用总结(五)结合MultiType展示多类型列表
- Android DataBinding使用总结(四)多类型列表展示
- Android DataBinding使用总结(三)列表展示
- Android 复杂的多类型列表视图新写法:MultiType 3.0
- android 使用DataBinding问题总结
- Android DataBinding使用总结(一)
- Android DataBinding使用总结(二)
- Android 复杂的列表视图新写法 MultiType
- android 复杂的列表视图新写法MultiType
- Android SearchView结合Filter实现列表检索功能使用总结
- 结合 MultiType 实现加载更多
- DataBinding的基本使用(五)
- Android使用ListView展示列表数据
- Android--DataBinding基础使用
- Android使用DataBinding入门
- android中使用DataBinding
- Android dataBinding 使用记录
- Android Databinding简单使用
- mysql中文乱码问题
- 离散题目15
- Win32 Socket select模型
- JPA Spring-Data-JPA hibernate mybatis
- caffe中solver.prototxt参数说明
- Android DataBinding使用总结(五)结合MultiType展示多类型列表
- JAVA初涉反射
- Ubuntu下安装QQ国际版
- WebBrowser与IE的关系,如何设置WebBrowser工作在IE9、10、11模式下?
- 真是该警觉了
- JavaWeb会话管理之浏览过的商品
- CSS属性列表
- Linux IO实时监控iostat命令详解
- 170601 逆向-CrackMe之008