使用Databinding为Recyclerview使用同一个ViewHolder加载不同Item

提示:在阅读本篇文章前,你最好对android databinding有一定了解,本文使用的代码均为kotlin,但是不用担心,都很简单

最近在写项目的时候使用了databinding技术,突发奇想,databinding是不是也能应用于recyclerview中,让加载多个不同的item更简单呢。在网上搜索过后读到了这篇文章,发现作者巧妙的使用了原有的函数来实现,在结合了自身使用实践之后,就有了现在这篇博客。

提问环节

为了让阅读过程更有目的性,先提几个问题,让大家带着问题来阅读

adaper部分

Q1:onCreateViewHolder中怎么动态的创建不同类型的ViewHolder

Q2:onBindViewHolder中怎么绑定不同类型的对象到viewHolder里

viewholder部分

Q3:怎么把传过来的不同类型对象绑定到layout上面

我们先来看看base adapter的代码

onCreateViewHolder函数里我们首先初始化了一个layoutInflater,再使用DataBindingUtil创建了一个viewDatabinding对象,注意到这里的第二个参数很奇怪,居然是viewType,这是为什么呢,我们接下来会分析到。在函数的最后,我们创建了一个viewholder并返回,构造参数传入了我们创建的ViewDatabinding对象。

接下来,是onBindViewHolder函数,我们首先使用接口getObjForPosition(position)获取到了一个类型为any?的对象,在kotlin里面,any基本可以等同于java中的object,并把这个对象通过viewholder的bind方法与viewholder进行了绑定操作

重写了getItemViewType方法,在这个方法里,我们通过另一个接口getLayoutIdForPosition获取到了一个类型为Int的返回值,通过这个函数,我们可以看出,这种使用方法把layout id当作了itemviewtype,在一个Int对象中传递了两个信息,同时由于layout id不会重复,又保证了itemtype的唯一性。

总结1:
到了这里,我们可以回答前两个问题了

Q1:onCreateViewHolder中怎么动态的创建不同类型的ViewHolder

并没有创建不同类型的viewholder,只使用了一个MyViewHolder

Q2:onBindViewHolder中怎么绑定不同类型的对象到viewHolder里

通过抽象接口getLayoutIdForPosition将layout id作为返回值在getItemViewType中返回,再在onBindViewHolder中使用抽象接口getObjForPosition获得类型为Any?的对象并绑定到viewholder实现了将不同类型的对象绑定到viewHolder中

我们来看一个具体的adapter例子

实现了上面提到的两个抽象接口,一个返回了对象的数量,一个返回了根据位置计算的layout id

viewholder部分

通过上述的过程,我们又会产生新的疑问,并没有使用多个viewholder来适配多个item,那是怎么使用同一个viewholder来搭配不同的layout的呢?内部又是怎么绑定的呢?

先来看一个viewHolder的代码

我们看到构造参数,是一个ViewDatabinding类型,在bind函数里,使用viewdatabinding对象的setVariable传入了参数obj,并且调用了executePendingBindings进行刷新,这样,我们的界面上就可以访问这个obj类了。

看一个layout的例子

Q&A

现在我们可以回答全部的问题了
Q1:onCreateViewHolder中怎么动态的创建不同类型的ViewHolder

并没有创建不同类型的viewholder,只使用了一个MyViewHolder

Q2:onBindViewHolder中怎么绑定不同类型的对象到viewHolder里

通过抽象接口getLayoutIdForPosition将layout id作为返回值在getItemViewType中返回,再在onBindViewHolder中使用抽象接口getObjForPosition获得类型为Any?的对象并绑定到viewholder实现了将不同类型的对象绑定到viewHolder中

Q3:怎么把传过来的不同类型对象绑定到layout上面

使用viewdatabinding的setVariable方法直接绑定到具体的变量上,再在布局中使用的时候指定类型,直接使用即可

此套方法巧妙的利用了databinding的特点,给adapter中itemtype赋予更多的含义,来实现了同一个viewholder对应不同布局的目的,十分的巧妙,尤其是给viewtype赋予更多含义,让人联想到了android view里面的measurespec,同样是给一个int赋予多重含义

u3coding
A software developer

Leave a Comment

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.