当前位置:

Android databinding:RecycleView使用和(二)

访客 2024-04-24 691 0

一、介绍

如果你刚看这边,并不了解databinding的使用,可以查看:Androiddatabinding的接入使用与详解(一)

Activity和fragment的数据绑定相对比较简单一些,在Android开发中recycleview使用频率也比较高。关于recycleview的数据绑定,接下来会做一个简单的介绍

二、Recycleview数据绑定

recycleview的数据绑定分为recycleview和adapter

1.RecycleView

recycleview的view正常在布局中设置,如果你想要databind来初始化,按databind的布局设置即可。data节点可以不写

  • <?xmlversion="1.0"encoding="utf-8"?>
  • <layoutxmlns:android="http://schemas.android.com/apk/res/android">
  • <LinearLayout
  • android:layout_width="match_parent"
  • android:layout_height="match_parent"
  • android:orientation="vertical">
  • <androidx.recyclerview.widget.RecyclerView
  • android:id="@id/recycleview"
  • android:layout_width="match_parent"
  • android:layout_height="match_parent"/>
  • </LinearLayout>
  • </layout>
  • 这样就就会生成对应的文件。

  • classDataBindRecycleViewActivity:BaseActivity(){
  • lateinitvardatabind:LayoutRecycleviewBinding;
  • lateinitvaradapter:MyAdapter
  • overridefunonCreate(savedInstanceState:Bundle?){
  • super.onCreate(savedInstanceState)
  • databind=DataBindingUtil.setContentView(this,R.layout.layout_recycleview)
  • varmanager=LinearLayoutManager(this)
  • manager.orientation=LinearLayoutManager.VERTICAL
  • databind.recycleview.layoutManager=manager
  • adapter=MyAdapter(getData(),this);
  • databind.recycleview.adapter=adapter
  • adapter.notifyDataSetChanged()
  • databind.recycleview.invalidate()
  • databind.btnSubmit.setOnClickListener{
  • toast("当前数据量:${databind.recycleview.childCount}")
  • }
  • }
  • fungetData():List<*>{
  • varlist=ArrayList<People>()
  • for(iin0until100){
  • varpeople=People()
  • people.name="我是第${i}"
  • list.add(people)
  • }
  • returnlist
  • }
  • }
  • 2、adapter的databind处理

    adapter核心在于如下几个地方

    ViewHolder继承

    onCreateViewHolder

    onBindViewHolder

    接下来我们会分解一下这些区域

    1.onCreateViewHolder

    view的创建和fragment/Actvity不一样,这边的view创建是DataBindingUtil.inflate

  • publicstatic<TextendsViewDataBinding>Tinflate(@NonNullLayoutInflaterinflater,
  • intlayoutId,@NullableViewGroupparent,booleanattachToParent)
  • 实战如下:

  • vardatabind=DataBindingUtil.inflate<LayoutItemTextDatabindBinding>(
  • LayoutInflater.from(context),
  • R.layout.layout_item_text_databind,
  • parent,
  • false
  • )
  • varviewholder=ViewHolder(databind);
  • returnviewholder
  • 2.ViewHolder继承

    创建完view,这时候需要初始化view。

    1.非databind创建

    非databind直接继承RecyclerView.ViewHolder,然后通过构造器的itemview来初始化

  • innerclassViewHolder(varroot:View):
  • RecyclerView.ViewHolder(root){
  • vartext=root.findViewById(R.id.text_title)asTextView
  • }
  • 2.databind完成ViewHolder的初始化

    由于onCreateViewHolder中已完成了databind常见,所以,view也同时完成了初始化

  • innerclassViewHolder(vardtabind:LayoutItemTextDatabindBinding):
  • RecyclerView.ViewHolder(dtabind.root){
  • fungetDataBind():LayoutItemTextDatabindBinding{
  • returndtabind;
  • }
  • }
  • 只需要将dataind.root传递给ViewHolder即可。无须再去初始化

    3、onBindViewHolder数据绑定

    数据绑定依旧在onBindViewHolder中进行。在绑定数据这边有两种

    1、如果你是通过databind来完成,并且layout布局中已映射好,那我们只需要更新数据源即可。

  • overridefunonBindViewHolder(holder:ViewHolder,position:Int){
  • //TODO("Notyetimplemented")
  • holder.dtabind.item=getItemObject(position)
  • }
  • 注意:如果采取映射,并且view中已绑定了,那我们在onBindViewHolder中不要再通过代码去设置,这样会导致recycleview不滑动,view虽然绘制,但是databind默认加载是空数据,这样就会导致是空白,只有滑动可见后,通过我们手动设置的数据取填充

    错误写法:

  • overridefunonBindViewHolder(holder:ViewHolder,position:Int){
  • //TODO("Notyetimplemented")
  • holder.dtabind.textTitle.text=getItemValue(position)
  • }
  • 异常显示

    所以,如果你采取了databind,要去设置数据源,否则会有异常显示。

    完整的Adapter如下:

  • packagecom.example.wiik.testdemo.databinding.recycleview
  • importandroid.content.Context
  • importandroid.view.LayoutInflater
  • importandroid.view.ViewGroup
  • importandroid.widget.TextView
  • importandroidx.databinding.DataBindingUtil
  • importandroidx.databinding.ViewDataBinding
  • importandroidx.recyclerview.widget.RecyclerView
  • importcom.example.wiik.testdemo.R
  • importcom.example.wiik.testdemo.databinding.LayoutItemTextDatabindBinding
  • importcom.example.wiik.testdemo.databinding.data.People
  • classMyAdapter(varlist:List<*>,varcontext:Context):
  • RecyclerView.Adapter<MyAdapter.ViewHolder>(){
  • overridefungetItemCount():Int{
  • //TODO("Notyetimplemented")
  • returnif(list==null)0elselist.size
  • }
  • fungetItemValue(position:Int):String{
  • varitem=list?.get(position)asPeople
  • returnitem.name
  • }
  • fungetItemObject(position:Int):People{
  • varitem=list?.get(position)asPeople
  • returnitem
  • }
  • overridefunonCreateViewHolder(parent:ViewGroup,viewType:Int):ViewHolder{
  • //TODO("Notyetimplemented")
  • vardatabind=DataBindingUtil.inflate<LayoutItemTextDatabindBinding>(
  • LayoutInflater.from(context),
  • R.layout.layout_item_text_databind,
  • parent,
  • false
  • )
  • varviewholder=ViewHolder(databind);
  • returnviewholder
  • }
  • overridefunonBindViewHolder(holder:ViewHolder,position:Int){
  • //TODO("Notyetimplemented")
  • holder.dtabind.item=getItemObject(position)
  • }
  • innerclassViewHolder(vardtabind:LayoutItemTextDatabindBinding):
  • RecyclerView.ViewHolder(dtabind.root){
  • fungetDataBind():LayoutItemTextDatabindBinding{
  • returndtabind;
  • }
  • }
  • }
  • XML布局如下:

  • <?xmlversion="1.0"encoding="utf-8"?>
  • <layoutxmlns:android="http://schemas.android.com/apk/res/android">
  • <data>
  • <importtype="com.example.wiik.testdemo.databinding.data.People"/>
  • <variable
  • name="item"
  • type="People"/>
  • </data>
  • <LinearLayout
  • android:layout_width="match_parent"
  • android:layout_height="wrap_content"
  • android:orientation="vertical">
  • <TextView
  • android:id="@id/text_title"
  • android:layout_width="match_parent"
  • android:layout_height="wrap_content"
  • android:textSize="18dp"
  • android:text="@{item.name}"
  • android:textColor="@color/black"
  • />
  • </LinearLayout>
  • </layout>
  • 数据源Bean:

  • classPeople:BaseObservable(){
  • @get:Bindable
  • varhead=""
  • set(head){
  • field=head
  • notifyPropertyChanged(BR.head)
  • }
  • @get:Bindable
  • varaddress:String=""
  • set(value){
  • field=value
  • notifyPropertyChanged(BR.address)
  • }
  • @get:Bindable
  • varname:String=""
  • set(value){
  • field=value
  • notifyPropertyChanged(BR.name)
  • }
  • @get:Bindable
  • varage:Int=0
  • set(value){
  • field=value
  • notifyPropertyChanged(BR.age)
  • }
  • }
  • 四、数据源的介绍

    databind的数据源涉及到数据绑定,比如我这边使用了双向绑定,也就是说如果view的发送改变,bean对象数据也会发生改变

    BaseObservable@BindablenotifyPropertyChanged()

    1、BaseObservable:

    当数据发生变化,会通知更新view

    2、Bindable:

    在get方法修饰,用于双方绑定,该注解用于标记实体类中的get方法或“is”开头的方法,会通过Bindable在BR中生成对应的fieldId(Int型),如果未绑定,将无法生成,生成后便于

    notifyPropertyChanged(BR.myname)更新,更新的机制是根据BR中id的记录
  • @get:Bindable
  • varmyname=""
  • set(value){
  • field=value
  • notifyPropertyChanged(BR.myname)
  • }
  • 3、notifyPropertyChanged(BRid):

    当更新数据时,会更新BR下的id字段这个方法一般在set方法中使用

    BR和其他文件生成如下,这边生成和AIDL的以及room数据库一样

    对应文件生成

    关于数据绑定,这边只做简单的介绍,后期会出完整的数据使用。

    注意:

    如果adapter数据在更新出现UI异常,或者数据填充等问题,可以调用databind的executePendingBindings

    一般在设置完数据结束后再调用

    mBinding.executePendingBindings();

    发表评论

    • 评论列表
    还没有人评论,快来抢沙发吧~