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 完整示例
5.ViewModel与application绑定
在指定ViewModel关联的生命期对象时,系统提供了activity和fragment,可以使用Application与ViewModel绑定。
5.1在application中定义 modelStoreOwner
1 class NxxApp : 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 NxxApp 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'