当前位置:   article > 正文

databinding之RecycleView使用与讲解(二) BaseObservable kotlin_databinding kotlin baseobservable

databinding kotlin baseobservable

一 、介绍 
        通过上一篇databinding接入,我们已大概了解到databinding接入的流程和数据的简单绑定。

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

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

二、Recycleview数据绑定
recycleview的数据绑定分为recycleview和adapter

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

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <layout xmlns:android="http://schemas.android.com/apk/res/android">
  3.     <LinearLayout
  4.         android:layout_width="match_parent"
  5.         android:layout_height="match_parent"
  6.         android:orientation="vertical">
  7.         <androidx.recyclerview.widget.RecyclerView
  8.             android:id="@+id/recycleview"
  9.             android:layout_width="match_parent"
  10.             android:layout_height="match_parent" />
  11.     </LinearLayout>
  12. </layout>

这样就就会生成对应的文件。登录后复制 

  1. class DataBindRecycleViewActivity : BaseActivity() {
  2.     lateinit var databind: LayoutRecycleviewBinding;
  3.     lateinit var adapter: MyAdapter
  4.     override fun onCreate(savedInstanceState: Bundle?) {
  5.         super.onCreate(savedInstanceState)
  6.         databind = DataBindingUtil.setContentView(this, R.layout.layout_recycleview)
  7.         var manager = LinearLayoutManager(this)
  8.         manager.orientation = LinearLayoutManager.VERTICAL
  9.         databind.recycleview.layoutManager = manager
  10.         adapter = MyAdapter(getData(), this);
  11.         databind.recycleview.adapter = adapter
  12.         adapter.notifyDataSetChanged()
  13.         databind.recycleview.invalidate()
  14.         databind.btnSubmit.setOnClickListener {
  15.             toast("当前数据量:${databind.recycleview.childCount}")
  16.         }
  17.     }
  18.     fun getData(): List<*> {
  19.         var list = ArrayList<People>()
  20.         for (i in 0 until 100) {
  21.             var people = People()
  22.             people.name = "我是第${i}"
  23.             list.add(people)
  24.         }
  25.         return list
  26.     }
  27. }

2、adapter的databind处理
adapter核心在于如下几个地方

        ViewHolder继承
        onCreateViewHolder
        onBindViewHolder
接下来我们会分解一下这些区域

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

  1. public static <T extends ViewDataBinding> T inflate(@NonNull LayoutInflater inflater,
  2.             int layoutId, @Nullable ViewGroup parent, boolean attachToParent)

实战如下:

  1. var databind = DataBindingUtil.inflate<LayoutItemTextDatabindBinding>(
  2.             LayoutInflater.from(context),
  3.             R.layout.layout_item_text_databind,
  4.             parent,
  5.             false
  6.         )
  7.         var viewholder = ViewHolder(databind);
  8.         return viewholder

2.ViewHolder继承
创建完view,这时候需要初始化view。

1.非databind创建

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

  1. inner class ViewHolder(var root: View) :
  2.         RecyclerView.ViewHolder(root) {
  3.         var text = root.findViewById(R.id.text_title) as TextView
  4.     }

2.databind完成ViewHolder的初始化

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

  1. inner class ViewHolder(var dtabind: LayoutItemTextDatabindBinding) :
  2.         RecyclerView.ViewHolder(dtabind.root) {
  3.         fun getDataBind(): LayoutItemTextDatabindBinding {
  4.             return dtabind;
  5.         }
  6.     }


只需要将dataind.root传递给ViewHolder即可。无须再去初始化

3、onBindViewHolder数据绑定

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

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

  1. override fun onBindViewHolder(holder: ViewHolder, position: Int) {
  2. //        TODO("Not yet implemented")
  3.         holder.dtabind.item =getItemObject(position)
  4.     }


注意:如果采取映射,并且view中已绑定了,那我们在onBindViewHolder中不要再通过代码去设置,这样会导致recycleview不滑动,view虽然绘制,但是databind默认加载是空数据,这样就会导致是空白,只有滑动可见后,通过我们手动设置的数据取填充


错误写法:
 

  1. override fun onBindViewHolder(holder: ViewHolder, position: Int) {
  2. //        TODO("Not yet implemented")
  3.         holder.dtabind.textTitle.text=getItemValue(position)
  4.     }

异常显示

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

完整的Adapter如下:

  1. package com.example.wiik.testdemo.databinding.recycleview
  2. import android.content.Context
  3. import android.view.LayoutInflater
  4. import android.view.ViewGroup
  5. import android.widget.TextView
  6. import androidx.databinding.DataBindingUtil
  7. import androidx.databinding.ViewDataBinding
  8. import androidx.recyclerview.widget.RecyclerView
  9. import com.example.wiik.testdemo.R
  10. import com.example.wiik.testdemo.databinding.LayoutItemTextDatabindBinding
  11. import com.example.wiik.testdemo.databinding.data.People
  12. class MyAdapter(var list: List<*>, var context: Context) :
  13. RecyclerView.Adapter<MyAdapter.ViewHolder>() {
  14. override fun getItemCount(): Int {
  15. // TODO("Not yet implemented")
  16. return if (list == null) 0 else list.size
  17. }
  18. fun getItemValue(position: Int): String {
  19. var item = list?.get(position) as People
  20. return item.name
  21. }
  22. fun getItemObject(position: Int): People {
  23. var item = list?.get(position) as People
  24. return item
  25. }
  26. override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
  27. // TODO("Not yet implemented")
  28. var databind = DataBindingUtil.inflate<LayoutItemTextDatabindBinding>(
  29. LayoutInflater.from(context),
  30. R.layout.layout_item_text_databind,
  31. parent,
  32. false
  33. )
  34. var viewholder = ViewHolder(databind);
  35. return viewholder
  36. }
  37. override fun onBindViewHolder(holder: ViewHolder, position: Int) {
  38. // TODO("Not yet implemented")
  39. holder.dtabind.item =getItemObject(position)
  40. }
  41. inner class ViewHolder(var dtabind: LayoutItemTextDatabindBinding) :
  42. RecyclerView.ViewHolder(dtabind.root) {
  43. fun getDataBind(): LayoutItemTextDatabindBinding {
  44. return dtabind;
  45. }
  46. }
  47. }

 

XML布局如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <layout xmlns:android="http://schemas.android.com/apk/res/android">
  3.     <data>
  4.         <import type="com.example.wiik.testdemo.databinding.data.People" />
  5.         <variable
  6.             name="item"
  7.             type="People" />
  8.     </data>
  9.     <LinearLayout
  10.         android:layout_width="match_parent"
  11.         android:layout_height="wrap_content"
  12.         android:orientation="vertical">
  13.         <TextView
  14.             android:id="@+id/text_title"
  15.             android:layout_width="match_parent"
  16.             android:layout_height="wrap_content"
  17.             android:textSize="18dp"
  18.             android:text="@{item.name}"
  19.             android:textColor="@color/black"
  20.             />
  21.     </LinearLayout>
  22. </layout>

数据源Bean:

  1. class People : BaseObservable() {
  2.     @get:Bindable
  3.     var head = ""
  4.         set(head) {
  5.             field = head
  6.             notifyPropertyChanged(BR.head)
  7.         }
  8.     @get:Bindable
  9.     var address: String = ""
  10.         set(value) {
  11.             field = value
  12.             notifyPropertyChanged(BR.address)
  13.         }
  14.     @get:Bindable
  15.     var name: String = ""
  16.         set(value) {
  17.             field = value
  18.             notifyPropertyChanged(BR.name)
  19.         }
  20.     @get:Bindable
  21.     var age: Int = 0
  22.         set(value) {
  23.             field = value
  24.             notifyPropertyChanged(BR.age)
  25.         }
  26. }

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

BaseObservable + @Bindable + notifyPropertyChanged()

1、BaseObservable :
        当数据发生变化,会通知更新view

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

notifyPropertyChanged(BR.myname)更新,更新的机制是根据BR中id的记录

  1. @get:Bindable
  2.     var myname = ""
  3.     set(value) {
  4.         field=value
  5.         notifyPropertyChanged(BR.myname)
  6.     }


3、notifyPropertyChanged(BR+id):
        当更新数据时,会更新BR下的id字段这个方法一般在set方法中使用

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

对应文件生成

关于数据绑定,这边只做简单的介绍,后期会出完整的数据使用。  
注意:
        如果adapter数据在更新出现UI异常,或者数据填充等问题,可以调用databind的executePendingBindings

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

mBinding.executePendingBindings();


-----------------------------------
©著作权归作者所有:来自51CTO博客作者蜗牛丶Zhao的原创作品,请联系作者获取转载授权,否则将追究法律责任
Android databinding之RecycleView使用与讲解(二)一 、介绍
https://blog.51cto.com/u_16065093/6182752

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/320719
推荐阅读
相关标签
  

闽ICP备14008679号