ViewModel、LiveData 使用

ViewModel、LiveData 使用

官方中文教学地址

在看以下内容之前,如果对DataBinding不够熟悉,建议先对DataBinding进行了解。

Android DataBinding 使用博客说明

Android DataBinding 使用测试代码

:ViewModel+LiveData+DataBinding使用

CSDN:ViewModel+LiveData+DataBinding使用

ViewModel 简介

ViewModel类是用来保存UI数据的类,它会在配置变更(即 Configuration Change,例如手机屏幕的旋转)之后继续存在;我们都知道,当手机屏幕发生旋转的时候,Activity会被重新创建,也就是说生命周期又将从onCreate开始,如果你此时不及时保存,那么一些UI数据将会丢失,这样肯定是会出问题的。但是,ViewModel并不会受此影响,即便手机屏幕发生旋转,ViewModel依然存在,这样的话Activity的UI数据便可以保存下来。

ViewModel 使用说明、注意

  1. 所有Activity的UI相关数据应该保存在ViewModel中,而不是保存在Activity中。这样做的好处是,在配置变更的时候,你应用的UI数据仍然存在。即使ViewModel这么强大,但它也不应该不承担过多责任,当有UI数据处理等相关事件建议创建Presenter类,或者创建一个更成熟的架构。
  2. Activity负责展示UI数据,并接收互动(一般来说是与用户的互动)。但是Activity不应当处理这些互动。
  3. 在应用需要加载数据或者保存数据的时候,建议创建一个Repository的存储区类,里面放置存储与加载应用数据的API。
  4. ViewModel不应持有Context,就像之前说的:

    它会在配置变更(即 Configuration Change,例如手机屏幕的旋转)之后继续存在。

所以,ViewModel生命周期远比Activity,Fragment等生命周期更长,具体如下图所示。如果你这样做了,加入在屏幕旋转情况下,原Activity将会销毁,新的Activity将会被创建。而ViewModel会一直持有原Activity,这样便会造成内存泄漏。如果你的ViewModel确实需要Context,那么你的ViewModel可以继承AndroidViewModel,这样你的ViewModel中会有Application的引用。

  1. ViewModel不应当取代onSaveInstanceState方法。尽管ViewModel很出色了,但是它和onSaveInstanceState依然是相辅相成的作用。因为,当进程被关闭时,ViewModel将会被销毁,但是onSaveInstanceState不会受到影响。

ViewModel 使用

ViewModel 引入

  1. android.support 形式

     implementation "android.arch.lifecycle:extensions:1.1.1"
     implementation "android.arch.lifecycle:viewmodel:1.1.1"
    
  2. androidx 支持(如下方式引入,包含了ViewModel和LiveData)

     implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
     annotationProcessor "androidx.lifecycle:lifecycle-compiler:2.0.0"
    

ViewModel 用法

  1. 新建数据实体类,作为UI需要使用的数据

     data class User(var name: String = "", var age: Int = 0, var address: String = "")
    
  2. 新建我的ViewModel类 UserViewModel 继承至 ViewModel

     class UserViewModel:ViewModel() {
         var user = User("张三",25,"浙江省杭州市")
     }
    
  3. 在Activity/Fragment中实例化

     class MainActivity : AppCompatActivity() {
         override fun onCreate(savedInstanceState: Bundle?) {
             super.onCreate(savedInstanceState)
             setContentView(R.layout.activity_main)
     
             var userViewModel = ViewModelProviders.of(this).get(UserViewModel::class.java)
         }
     }
    

经过上面的步骤,我们的ViewModel就算建立好了,现在看上去并没有什么实际的意义。但是不要急,慢慢的往下看,当他和LiveData以及DataBinding一起使用的时候就会发现新世界了。

注意点

  1. ViewModel只提供一个默认的无参构造函数,如果你需要一个有参构造函数,那么就需要使用ViewModelFactory这个类,具体使用方法如下所示:

     // 数据实体类
     data class Student(var name: String, var address: String = "")
    
     // ViewModel 类
     class StudentViewModel(var student: Student) : ViewModel()
    
     // 建立 StudentViewModelFactory 类
     class StudentViewModelFactory(private var student: Student) : ViewModelProvider.NewInstanceFactory() {
         override fun  create(modelClass: Class): T {
             return StudentViewModel(student) as T
         }
     }
    
     // 在Activity/Fragment中使用
     class MainActivity : AppCompatActivity() {
         override fun onCreate(savedInstanceState: Bundle?) {
             super.onCreate(savedInstanceState)
             var factory = StudentViewModelFactory(Student("李四","浙江省杭州市"))
             var viewModel = ViewModelProviders.of(this, factory).get(StudentViewModel::class.java)
     }
    

    }

  2. 当我们的 ViewModel 中需要使用Context时,也不应该从 Activity/Fragment 中传递,而是应该让我们的ViewModel 继承 AndroidViewModel,这样就能在 ViewModel 中使用 Application了

     class UserViewModel(application: Application) :AndroidViewModel(application) {
         var user = User("张三",25,"浙江省杭州市")
     }
    

LiveData简介

LiveData是一个可观察的数据持有者类。与常规可观察性不同,LiveData具有生命周期感知能力,这意味着它尊重其他应用程序组件(例如Activity、Fragment或Service)的生命周期。这种感知确保LiveData只更新处于活动生命周期状态(Observer 的 Lifecycle 对象处于 STARTED 或者 RESUMED 状态)的应用程序组件观察者。

LiveData 的优点

  1. 具有生命周期感知能力,可以做到在组件处于激活状态的时候才会回调相应的方法,从而刷新相应的 UI。
  2. 不用担心发生内存泄漏
  3. 当 config 导致 Activity 重新创建的时候,不需要手动取处理数据的储存和恢复。它已经帮我们封装好了。(需要使用ViewModel)
  4. 当 Actiivty 不是处于激活状态的时候,如果你想 Livedata setValue 之后立即回调 obsever 的 onChange 方法,而不是等到 Activity 处于激活状态的时候才回调 obsever 的 onChange 方法,你可以使用 ObserveForever 方法,但是你必须在 onDestroy 的时候 removeObserver。

LiveData 使用

LiveData 引入

  1. android.support 形式

     implementation "android.arch.lifecycle:livedata:1.1.1"
    
  2. androidx 支持(如下方式引入,包含了ViewModel和LiveData)

     implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
     annotationProcessor "androidx.lifecycle:lifecycle-compiler:2.0.0"
    

LiveData 基本使用

  1. 直接使用默认值设置

     // data class
     data class User(var name: String = "", var age: Int = 0, var address: String = "")
    
     // ViewModel 
     class UserViewModel : ViewModel() {
         var userLiveData:MutableLiveData = MutableLiveData()
         init {
             // 初始化是提供默认值
             userLiveData.value = User("张三",25,"浙江省杭州市")
         }
     }
    
     // Activity 
     class MainActivity : AppCompatActivity() {
         override fun onCreate(savedInstanceState: Bundle?) {
             super.onCreate(savedInstanceState)
             setContentView(R.layout.activity_main)
     
             var userViewModel = ViewModelProviders.of(this).get(UserViewModel::class.java)
             text_view.text = userViewModel.userLiveData.value.toString()
         }
     }
    
     // activity_main.xml
     
     
     
         
  2. 点击事件修改值之后实时更新

     // 只需要在 Activity 的 onCreate() 方法中增加以下代码即可
    
      // 增加改变监听
     userViewModel.userLiveData.observe(this, Observer {user ->
         text_view.text = user.toString()
     })
     // 点击按钮,改变User
     bt_change.setOnClickListener {
         userViewModel.userLiveData.postValue(User("李四",28,"湖南省长沙市"))
     }
    

LiveData 进阶使用

  1. map() :把一个数据类型变换为另外一个数据类型

     // 将 User 对象变为 String
     private fun map(userLiveData: MutableLiveData): LiveData {
         return Transformations.map(userLiveData) { user ->
             user.name
         }
     }
    
     // 使用
     map(userViewModel.userLiveData).observe(this, Observer {
         text_view.text = it
     })
    
  2. switchMap() : 把一个数据变化为另外一个 LiveData

     // 在回调中创建 LiveData 类型数据返回
     private fun switchMap(userLiveData: MutableLiveData): LiveData {
         return Transformations.switchMap(userLiveData) {
             var result = MutableLiveData()
             result.postValue(it.name)
             return@switchMap result
         }
     }
    
     // 使用
     switchMap(userViewModel.userLiveData).observe(this, Observer {
         text_view.text = it
     })
    
  3. MediatorLiveData : LiveData的一个子类,允许合并多个LiveData源。MediatorLiveData对象的观察者随后会在任何原始LiveData源对象更改时触发

     / data class
     data class User(var name: String = "", var age: Int = 0, var address: String = "")
    
     // Activity 
     class MainActivity : AppCompatActivity() {
         override fun onCreate(savedInstanceState: Bundle?) {
             super.onCreate(savedInstanceState)
             setContentView(R.layout.activity_main)
     
             var userViewModel = ViewModelProviders.of(this).get(UserViewModel::class.java)
    
             var mediatorLiveData: MediatorLiveData = MediatorLiveData()
             var user1 = MutableLiveData()
             var user2 = MutableLiveData()
             mediatorLiveData.addSource(user1) {
                 Log.i("bbb", it.toString())
                 text_view.text = it.address
             }
             mediatorLiveData.addSource(user2) {
                 Log.i("ccc", it.toString())
                 text_view.text = it.address
             }
             // 这一步不能省略
             mediatorLiveData.observe(this, Observer {
                 Log.i("aaa", it.toString())
                 // 此处的返回值好像没有作用,日志也没有打印,
                 // 但是该 mediatorLiveData.observe 不能省略,省略的话,界面不能更新
                 text_view.text = it.name
             })
     
             // 点击按钮,改变User
             var flag = false
             bt_change.setOnClickListener {
                 if (flag)
                     user1.postValue(User("王五", 26, "深圳"))
                 else
                     user2.postValue(User("赵六", 27, "上海"))
                 flag = !flag
             }
         }
     }
    

MutableLiveData 的 setValue() 和 potValue() 方法

  • setValue():只能在主线程设置Value
  • postValue():可以在子线程设置Value

ViewModel+LiveData+DataBinding使用

:ViewModel+LiveData+DataBinding使用
CSDN:ViewModel+LiveData+DataBinding使用

你可能感兴趣的:(ViewModel、LiveData 使用)