1.学会了LiveData可以干什么?
答:可以得到一个可观察并具有生命周期感知能力,存储任何数据类型的封装容器。还可以利用LiveData的特性,自己写一个简单的事件总线,类似于EventBus。
2.LiveData的官方介绍:
LiveData 是一种具有生命周期感知能力、可观察的数据存储器类。
LiveData
的部分特性如下:
LiveData
可存储数据;LiveData
是一种可与任何类型数据搭配使用的封装容器。LiveData
是可观察的,这意味着当LiveData
对象存储的数据发生更改时,观察器会收到通知。LiveData
具有生命周期感知能力。当您将观察器附加到LiveData
后,观察器就会与 LifecycleOwner(通常是 activity 或 fragment)相关联。LiveData
仅更新处于活跃生命周期状态(例如 STARTED 或 RESUMED)的观察器。您可以在此处详细了解LiveData
和观察。
3.ViewModel的官方介绍:
ViewModel 类是一种业务逻辑或屏幕级状态容器。它用于将状态公开给界面,以及封装相关的业务逻辑。 它的主要优点是,它可以缓存状态,并可在配置更改后持久保留相应状态。这意味着在 activity 之间导航时或进行配置更改后(例如旋转屏幕时),界面将无需重新提取数据。
ViewModel 的优势
ViewModel 的替代方案是保存要在界面中显示的数据的普通类。在 activity 或 Navigation 目的地之间导航时,这可能会造成问题。此时,如果您不利用保存实例状态机制存储相应数据,系统便会销毁相应数据。ViewModel 提供了一个便捷的数据持久性 API,可以解决此问题。
ViewModel 类的主要优势实际上有两个方面:
- 它允许您持久保留界面状态。
- 它可以提供对业务逻辑的访问权限。
持久性
ViewModel 允许数据在 ViewModel 保有的状态和 ViewModel 触发的操作结束后持久存在。这种缓存意味着在常见的配置更改(例如屏幕旋转)完成后,您无需重新提取数据。
作用域
实例化 ViewModel 时,您会向其传递实现 ViewModelStoreOwner 接口的对象。它可能是 Navigation 目的地、Navigation 图表、activity、fragment 或实现接口的任何其他类型。然后,ViewModel 的作用域将限定为 ViewModelStoreOwner
的 Lifecycle。它会一直保留在内存中,直到其 ViewModelStoreOwner
永久消失。
有一系列类是 ViewModelStoreOwner
接口的直接或间接子类。直接子类为 ComponentActivity、Fragment 和 NavBackStackEntry。如需查看间接子类的完整列表,请参阅 ViewModelStoreOwner 参考文档。
当 ViewModel 的作用域 fragment 或 activity 被销毁时,异步工作会在作用域限定到该 fragment 或 activity 的 ViewModel 中继续进行。这是持久性的关键。
如需了解详情,请参阅下文有关 ViewModel 生命周期的部分。
好了,前面都是概念性的东西,下面我们进入实战,手写一个在ViewModel中搭配LiveData的使用Demo。(请允许我全程使用Kotlin来写,对于还在对Kotlin抱以观望的童鞋致歉,哈哈哈~)
4.创建Application,因为本次我们继承的是AndroidViewModel,并且是直接在Application中初始化的(Ps:MyApplication记得在AndroidManifest.xml中引用哦)
package com.xcy.myjetpackdemo
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
class AppViewModel(application: Application) : AndroidViewModel(application) {
private var _titleLiveData : MutableLiveData<String> = MutableLiveData()
val titleLiveData : LiveData<String> = _titleLiveData
fun setTitle(title : String){
_titleLiveData.postValue(title)
}
}
package com.xcy.myjetpackdemo
import android.app.Application
import androidx.lifecycle.ViewModelProvider
class MyApplication : Application() {
companion object{
lateinit var appViewModel : AppViewModel
}
override fun onCreate() {
super.onCreate()
//创建ViewModel
appViewModel = ViewModelProvider.AndroidViewModelFactory.getInstance(this).create(AppViewModel::class.java)
}
}
5.然后在MainActivity中往ViewModel中LiveData存值,并跳转到OtherActivity.kt
package com.xcy.myjetpackdemo
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import androidx.activity.viewModels
class MainActivity : AppCompatActivity() {
private lateinit var mEtInput : EditText
private lateinit var mBtn : Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mEtInput = findViewById(R.id.et_input_main)
mBtn = findViewById(R.id.btn_main)
mBtn.setOnClickListener {
var inputValue = mEtInput.text.trim().toString()
if (!inputValue.isNullOrEmpty()){
//存值
MyApplication.appViewModel.setTitle(inputValue)
//跳转到OtherActivity查看存值情况
var intent = Intent(this@MainActivity,OtherActivity::class.java)
startActivity(intent)
}
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:id="@+id/et_input_main"
android:hint="Please input Value."
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_main"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_input_main"
android:layout_width="wrap_content"
android:text="提交"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
6.查看ViewModel里LiveData存的值
package com.xcy.myjetpackdemo
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
/**
* 接收值的Activity
*/
class OtherActivity : AppCompatActivity() {
private lateinit var tvTitle : TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_other)
tvTitle = findViewById(R.id.tv_title)
//监听titleLiveData里面值的变化
MyApplication.appViewModel.titleLiveData.observe(this) {
tvTitle.text = it
}
}
}
activity_other.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".OtherActivity">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="20sp"
tools:text="Hello" />
</androidx.constraintlayout.widget.ConstraintLayout>
7.运行效果展示
完结撒❀~