全文阅读预计 15 分钟
这可能是你看过的最清晰明了的讲解
主题 👇
官方定义:
LiveData
是一种可观察的数据存储器类。与常规的可观察类不同,LiveData
可感知生命周期,也就是说它遵循其他应用组件(如Activity、Fragment
或Service
)的生命周期。这种感知能力可确保LiveData
仅更新处于活跃生命周期状态的应用组件观察者。
特性:如果观察者(由
Observer
类表示)的生命周期处于STARTED
或RESUMED
状态,则LiveData
会认为该观察者处于活跃状态。LiveData
只会将更新通知给活跃的观察者。为观察LiveData
对象而注册的非活跃观察者不会收到更改通知
LifecycleOwner
接口所生成的对象所配对的观察者,你可以注册和实现它。有了这种关系,当响应的Lifecycle
对象的状态变为DESTROYED
时,便可以移除此观察者。对于Activity
和Fragment
特别有用,因为它们可以放心地观察LiveData
对象而不必担心内存泄漏(当Activity
和Fragment
的生命周期被销毁时,系统会立即退订它们)
对于 LifecycleOwner 有疑问? 请进入此链接学习我对于 Lifecycles 的快速及通俗讲解。 全文阅读预计 10 分钟。
使用 👇
引入 LiveData
// build.gradle
dependencies {
// ViewModel and LiveData
def lifecycle_version = "2.1.0"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
// 或
// implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"
// 前者创建一个变量主要是便于管理,假如说你还引入了 lifecycle 的其它东西那么他们都同时使用这个变量的版本号就好,以后升级版本的时候只需要改一个地方
}
创建 LiveData 对象
对于 ViewModel 有疑问? 请进入此链接学习我对于 ViewModel 的快速及通俗讲解。
public class FiveViewModel extends ViewModel {
// 创建一个 String 类型的 LiveData
// 至于 MutableLiveData 是什么文末有讲
private MutableLiveData<String> currentName;
public MutableLiveData<String> getCurrentName() {
if (currentName == null) {
currentName = new MutableLiveData<>();
}
return currentName;
}
}
如此,一个 LiveData 就创建好了,LiveData
通常存储在 ViewModel
中。也请确保它存储在 ViewModel
中。
为什么要将 LiveData
对象存储在 ViewModel
对象中,而不是将其存储在 Activity
或 Fragment
中?
- 避免
Activity、Fragment
过于庞大。我们ViewModel
的作用本来就是为了使View
和Model
分离及其它一些优势,这些界面控制器(Activity、Fragment等)
负责显示数据,但不负责存储数据状态 - 将
LiveData
实例与特定的Activity、Fragment
实例分离开
,并使对象在配置更改后继续存在
观察 LiveData 对象
public class FiveActivity extends AppCompatActivity {
private FiveViewModel model;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
model = ViewModelProviders.of(this).get(FiveViewModel.class);
Observer<String> observer = new Observer<String>() {
@Override
public void onChanged(String s) {
// 这样,每次 FiveViewModel 中的 currentName 变量的值发生变化时,都会进入到这个 onChanged() 方法
// textView.setText(s);
}
};
model.getCurrentName().observe(this, observer);
// 使用 observe() 方法将 Observer 对象附加到 LiveData 对象。
// observe() 会采用 LifecycleOwner 对象(因为第一个参数 this 就是传入的当前这个 Activity 的 LifecycleOwner)。
// 有 LifecycleOwner 的好处是 LiveData 会自己观测 界面控制器(Activity、Fragment)的生命周期
// 当然,如果你不想提供 LifecycleOwner 你可以通过 observeForever(Observer) 方法来注册
// 那么这种情况下,观察者就会被视为始终活跃状态,也意味着你需要在不使用它的时候通过 removeObserver(Observer) 方法移除这个观察者
}
}
小总结一下:
FiveViewModel
中currentName
是被观察者,每次当currentName
的值发生变化会反馈给FiveActivity
的观察者中的onChanged()
方法中
更新 LiveData 对象
可变:可被修改值的
不可变:不可被修改值
LiveData(不可变)
没有公开可用的方法来更新存储的数据。MutableLiveData(可变)
类公开了setValue(T)
和postValue(T)
方法
如果你需要修改存储在
LiveData
对象中的值,则必须使用这些方法(setValue、postValue)
。通常情况下会在ViewModel
中使用MutableLiveData
,然后ViewModel
只会向观察者
公开不可变的LiveData
对象
也就是 ViewModel
中一般都会用 MutableLiveData
因为它是可变的这样你才能设置数据,ViewModel
只会对观察者公开不可变的 LiveData
因为 View
和 Model
分离,不应该在 View(界面控制器)
中去操作数据方面的变化
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String anotherName = "John Doe";
model.getCurrentName().setValue(anotherName);
}
});
// setValue() 后会触发上面 FiveActivity 中观察者里的 onChanged() 方法
// 你可以根据你的需求使用来更改这个 MutableLiveData 的值,它们都会触发观察者并调用 onChanged()
- setValue:在主线程中使用
- postValue:在 worker 线程中使用
文末 👇
优势所在
LiveData
遵循观察者模式,当生命周期状态发生变化LiveData
会通知Observer
对象,你可以在Observer
对象中更新界面。观察者可以在每次收到发生更改时更新界面,而不是在每次应用数据发生更改时更新界面。(就是说当 LiveData 在数据发生变化时并且 LiveData 处于活跃状态就会更新界面,而不是应用数据发生变化就更新界面)
(具体下面有例子)- 观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理
LiveData 会观测 Lifecycle 的销毁,并在销毁时自我清理,用来阻止内存泄漏等问题的发生
- 如果观察者的生命周期处于非活跃状态(如返回栈中的
Activity
),则它不会接收任何LiveData
事件。当 Activity 停止时就会停止一些更新界面的操作等,避免了 Activity 停止造成的崩溃
- 界面组件只是观察相关数据,不会停止或恢复观察。
LiveData
将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。 - 如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的
Activity
会在返回前台后立即接收最新的数据。 - 如果由于配置更改(如设备旋转)而重新创建了
Activity
或Fragment
,它会立即接收最新的可用数据。 - 您可以使用单一实例模式扩展
LiveData
对象以封装系统服务,以便在应用中共享它们。LiveData
对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察LiveData
对象。
码字不易,还请动动小手左侧栏中点赞 👍,3Q