zoukankan      html  css  js  c++  java
  • android MVVM(2)用数据绑定关联VM 与 V ; viewModel 扩展包

    1.官方文档

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

    2.简介

      数据绑定库 可与MVVM 架构组件无缝协作。指定一下 binding的 lifecycleOwner 就可以了。如下:

     1 class PageFrgmt (var number : Int) : Fragment() {
     2 
     3     lateinit
     4     var binding     :   PageBinding
     5     val viewModel   :   DataViewModel by viewModels()
     6 
     7     fun initBinding(){
     8         binding.lifecycleOwner = this
     9         binding.number = number
    10         binding.data = viewModel.data
    11     }
    12 
    13     override fun onCreateView(
    14         inflater: LayoutInflater,
    15         container: ViewGroup?,
    16         savedInstanceState: Bundle?
    17     ): View? {
    18         binding = PageBinding.inflate(inflater,container,false)
    19         initBinding()
    20         return binding.root
    21     }
    22 }

    3.使用数据绑定与LiveData区别

    使用数据绑定时,有两种方式实现数据更新通知 :

    a. 使用  ObservableInt,ObservableFloat ... ObservableField<XX> 等

    • 缺点是这系列类不知道观察者(在mvvm架构中,通常是Activity,Fragment)的生命期变化,
    • 优点是不用在代码里写观察代码,如
      1        viewModel.loadUser().observe(viewLifecycleOwner){user->
      2             nameValue.setText(user.name)
      3             ageValue.setText(user.age.toString())
      4         }
    • 在android 3.1以上,可以直接把ObservableXXX 系列类,换成LiveData系列。

    b. 使用 BaseObservable 基类,这时无法替换成LiveData

    4.示例

    4.1 定义Data与Model

    Data:

     1 class Data : BaseObservable {
     2 
     3     constructor():super(){
     4         Log.e("MVVM_Data","constructor(), value = $value")
     5     }
     6     init{
     7         Log.e("MVVM_Data","init, value = $value")
     8         ++value
     9         name = "data$value"
    10     }
    11     @get:Bindable
    12     var name    =   "unknown_"
    13         set(value) {
    14             field = value
    15             notifyPropertyChanged(BR.name)
    16         }
    17 
    18     companion object : BaseObservable(){
    19         @get:Bindable
    20         @JvmStatic var value   =   0
    21             set(value) {
    22                 field = value
    23                 notifyPropertyChanged(BR.value)
    24             }
    25     }
    26 }

    Model

     1 class DataModel(var args : Bundle) {
     2 
     3     val liveData: MutableLiveData<Data> by lazy { initLiveData() }
     4     val data    :   Data  by lazy { initData() }
     5 
     6     fun initLiveData() : MutableLiveData<Data>{
     7         val data = Data().apply {
     8             name = "liveData"
     9         }
    10         return MutableLiveData(data)
    11     }
    12 
    13     fun initData() : Data{
    14         return Data().apply {
    15             name = "Data"
    16         }
    17     }
    18 
    19     fun loadData() : Data{
    20         return data
    21     }
    22 
    23     fun loadLiveData() : MutableLiveData<Data>{
    24         return liveData
    25     }
    26 }

    4.2 定义ViewModel

     1 class DataViewModel(var args : Bundle): ViewModel(),Observable {
     2 
     3     val model = DataModel(args)
     4 
     5     fun loadData() = model.loadData()
     6     fun loadLiveData() = model.loadLiveData()
     7 
     8     override fun onCleared() {
     9         super.onCleared()
    10     }
    11 
    12     override fun removeOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) {
    13     }
    14 
    15     override fun addOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) {
    16     }
    17 }

    由于ViewModel有参数,默认的 ViewModelFactory不支持,需要自定义一个 ViewModelFactory

    1 class DataViewModelFactory(var args : Bundle) : ViewModelProvider.Factory {
    2 
    3     override fun <T : ViewModel> create(modelClass: Class<T>): T {
    4         if (modelClass.isAssignableFrom(DataViewModel::class.java)) {
    5             return DataViewModel(args) as T
    6         }
    7         throw IllegalArgumentException("Unknown ViewModel class")
    8     }
    9 }

    4.3 在View中用数据绑定关联View与ViewModel

     1 class PageFrgmt (var number : Int) : Fragment() {
     2 
     3     companion object {  @JvmStatic var  VMSOwner  =   false }
     4 
     5     lateinit
     6     var binding     :   PageBinding
     7 
     8     val viewModel1  :   DataViewModel by lazy { initViewModel() }
     9     val viewModel2  :   DataViewModel by activityViewModels(this::factory)
    10     val viewModel3  :   DataViewModel by viewModels(this::ownerProducer,this::factory)
    11 
    12 
    13     fun factory() : DataViewModelFactory{
    14         return DataViewModelFactory(Bundle())
    15     }
    16     fun ownerProducer() : ViewModelStoreOwner {
    17         return this
    18     }
    19 
    20     fun initViewModel() : DataViewModel{
    21         return if (VMSOwner){
    22 //            ViewModelProvider(requireActivity()).get(DataViewModel::class.java)
    23             ViewModelProvider(requireActivity(), DataViewModelFactory(Bundle())).get(DataViewModel::class.java)
    24         }else{
    25 //            ViewModelProvider(this).get(DataViewModel::class.java)
    26             ViewModelProvider(this,DataViewModelFactory(Bundle())).get(DataViewModel::class.java)
    27         }
    28     }
    29 
    30     fun initBinding(){
    31         binding.lifecycleOwner = this
    32 //        val viewModel2  :   DataViewModel by activityViewModels(this::factory)
    33 //        val viewModel3  :   DataViewModel by viewModels(this::ownerProducer,this::factory)
    34         binding.data = if (VMSOwner) viewModel2.loadData() else viewModel3.loadData()
    35     }
    36 
    37     override fun onCreateView(
    38         inflater: LayoutInflater,
    39         container: ViewGroup?,
    40         savedInstanceState: Bundle?
    41     ): View? {
    42         Log.e("MVVM_TAG","PageFrgmt page $number onCreateView ,VMSOwner = $VMSOwner")
    43         binding = PageBinding.inflate(inflater,container,false)
    44         initBinding()
    45         return binding.root
    46     }
    47 //...
    48 }
    • 其中第8、9、10行:用3种方法定义了ViewModel成员
    • 第31行:指定了binding的生命期
    • 第34行:关联了view与ViewModel

    绑定布局

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <layout xmlns:android="http://schemas.android.com/apk/res/android"
     3     xmlns:app="http://schemas.android.com/apk/res-auto">
     4     <data>
     5         <variable name="data" type="com.example.mvvm2.model.Data" />
     6     </data>
     7     <androidx.constraintlayout.widget.ConstraintLayout
     8         android:background="#ffffff"
     9         android:layout_width="match_parent"
    10         android:layout_height="match_parent">
    11 
    12         <TextView
    13             ...
    14             android:text="@{@string/data_format(data.name,data.value),default=@string/data_format}"
    15            />
    16 
    17 
    18     </androidx.constraintlayout.widget.ConstraintLayout>
    19 </layout>

    4.4 完整示例

      https://github.com/f9q/mvvm2 

    5.ViewModel与application绑定

    在指定ViewModel关联的生命期对象时,系统提供了activity和fragment,可以使用Application与ViewModel绑定。

    5.1在application中定义 modelStoreOwner

    1 class XXXApp : MultiDexApplication(), ViewModelStoreOwner {
    2     val modelStoreOwner     =   ViewModelStore()
    3     override fun getViewModelStore(): ViewModelStore {
    4         return modelStoreOwner
    5     }
    6     //...
    7 }    

    5.2 关联ViewModel与Application

     1 class DeviceFrgmt : Fragment() {
     2     val viewModel      : DeviceViewModel   by lazy { initDeviceModel() }
     3     fun initDeviceModel() : DeviceViewModel{
     4         val app = activity?.application as XXXApp
     5         val vm = ViewModelProvider(app, DeviceViewModelFactory(app)).get(DeviceViewModel::class.java).apply {
     6             loadCallback    = this@DeviceFrgmt::loadDeviceCallback
     7             ...
     8         }
     9         return vm
    10     }
    11     fun initBinding(){
    12         binding.lifecycleOwner = this
    13         //...    
    14     }
    15 }

    6. 扩展包

    6.1 viewModels、activityViewModels

      4.3 节代码中的 activityViewModels 与 viewModels 可以简单构造viewModel ,它们所在包:

      implementation 'androidx.fragment:fragment-ktx:1.2.5'

    6.2 ViewModelProvider 

     4.3 节代码中的  ViewModelProvider 所在包:

      implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    class NurseApp : MultiDexApplication(), ViewModelStoreOwner {
    val modelStoreOwner = ViewModelStore()
    override fun getViewModelStore(): ViewModelStore {
    return modelStoreOwner
    }
  • 相关阅读:
    baremetal node & openstack hypervisor &openstack flavor
    bridge fdb vxlan nolearning
    bridge fdb 与vxlan
    FRRouting Architecture
    bridge fdb Command Output
    while循环和until语句
    Python私有属性和私有方法
    python面向对象封装案例2
    Python面向对象封装案例
    Python类和对象
  • 原文地址:https://www.cnblogs.com/mhbs/p/13392262.html
Copyright © 2011-2022 走看看