接着上一篇博客ViewModel,这一篇我们就来说一下一般配合ViewModel使用的LiveData
jetpack系列
第一篇:jetpack—Lifecycle的运用 第二篇:jetpack—ViewModel的了解 第三篇:jetpack—LiveData的使用
什么是LiveData?
官方说明:LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。如果观察者(由 Observer 类表示)的生命周期处于 STARTED 或 RESUMED 状态,则 LiveData 会认为该观察者处于活跃状态。LiveData 只会将更新通知给活跃的观察者。为观察 LiveData 对象而注册的非活跃观察者不会收到更改通知。
使用LiveData写一个示例参照官方文档上的步骤
1、创建 LiveData 的实例以存储某种类型的数据。这通常在 ViewModel 类中完成。那我们就先需要写一个viewModel,然后在创建LiveData实例。
class LiveDataViewModel : ViewModel() {
private val data = MyData()
private val liveData: MutableLiveData<MyData> by lazy {
MutableLiveData<MyData>()
}
override fun onCleared() {
super.onCleared()
}
}
注意: 1、看源码可知LiveData是一个抽象类,我们就不能直接 使用,但是我们可以使用他的子类,MutableLiveData 2、确保更新界面的LiveData对象储存在ViewModel对象中
然后我们需要加入更新数据的一个方法setUserData,和获取数据的方法getUserData,在更新数据的setUserData中给livedata设置数据liveData.value = data
class LiveDataViewModel : ViewModel() {
private val data = MyData()
private val liveData: MutableLiveData<MyData> by lazy {
MutableLiveData<MyData>()
}
fun getUserData(): LiveData<MyData> {
return liveData
}
fun setUserData(str: String) {
data.name = str
liveData.value = data
}
override fun onCleared() {
super.onCleared()
}
}
注意: Livedata提供给我们2个更新数据的方法,一个是PostValue 一个是setValue点击去看源码可以知道 postValue适用于非UI线程的异步线程 setValue是在UI线程中 我上面的示例并非异步线程中所以直接使用了setValue 2、创建可定义 onChanged() 方法的 Observer 对象,该方法可以控制当 LiveData 对象存储的数据更改时会发生什么。通常情况下,您可以在界面控制器(如 activity 或 fragment)中创建 Observer 对象。 就是在Activity中间我们需要创建一个观察者对数据进行观察
class MainActivity : AppCompatActivity() {
private lateinit var start: TextView
private lateinit var contentTv: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
start = findViewById(R.id.start)
contentTv = findViewById(R.id.contentTv)
val viewModel = ViewModelProvider(this)[LiveDataViewModel::class.java]
val liveData = viewModel.getUserData()
liveData.observe(this, {
contentTv.text =it.name
})
start.setOnClickListener {
viewModel.setUserData("改变改变")
}
}
}
然后我们点击按钮改变一下viewModel中LiveData的值然后看下是否改变了。 从上面劣质的Gif可以看出LiveData的例子是已经成功了,并且因为ViewModel的原因,并不会因为屏幕旋转而导致数据丢失,如果对ViewModel有什么疑问的话可以看下我的上一篇,目录在文章的开头已经给出来了
接下来就简单的分析一下liveData.observe 这个 方法看看他到底是怎么实现的 先看下源码
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
1、首先点击observe可以看到这个方法需要一个LifecycleOwner ,我们上面传的是this进去,当前的activity,又因为我们前面再说LifeCycle的时候说过了CompatActivity是已经实现了LifecycleOwner,不是太清楚的话可以看下前面的LifeCycle那一篇,所以说LiveData就拥有了感知生命周期的能力。 2、if (owner.getLifecycle().getCurrentState() == DESTROYED) { return; } 这句代码可以看出activity在生命周期结束的时候这个地方就直接return了不会在进行更新数据了。也就解决了有些地方因为activity生命周期结束而产生的内存溢出的问题。
接着往下看LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer); 看下LifecycleBoundObserver 这个类
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
1、可以看到 LifecycleBoundObserver 实现了LifecycleEventObserver 接口重写了onStateChanged 这个方法就是说在生命周期状态改变的是时候会去调用。
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
然后获取了当前的生命周期,如果是当前生命周期是Destroyed,就移除掉了这个观察者就不在往下进行了,反之调用activeStateChanged(shouldBeActive()); 方法保持当前观察者,然后传进去了一个方法shouldBeActive() 看下这个方法,返回的就是当前的生命周期的一个状态只有在start,resume,pause的时候才可以进行一个数据的更新
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
上面就已经分析了一个LiveData 的一个工作的原理。
我们可以看到除了 liveData.observe ,还有一个方法LiveData.observeForever 方法比对来看,用法都是一样的,但是observe 传了一个当前的Activity,当前的Activity又是继承CompatActivity是已经实现了LifecycleOwner ,进去相当于绑定了当前Activity的生命周期,从而让LiveData会跟随着Activity的生命周期, LiveData 会认为该观察者处于活跃状态。LiveData 只会将更新通知给活跃的观察者。 但是observeForever 并没有传递一个LifecycleOwner 那就是说LiveData的数据发生变化时,无论页面处于什么状态,observeForever() 都能收到通知。observeForever 也不会随着Activity的销毁而停止对LiveData的观察,所以我们必须在使用完成的时候手动调用removeObserver() 来停止对LiveData的观察,否者的话LiveData一直在激活的状态,你的Activity就不会被系统回收。
liveData.observe(this, {
contentTv.text =it.name
})
liveData.observeForever {
contentTv.text =it.name
}
LiveData基本上用到最多的也就是这些如果有什么说的不对的地方,还是麻烦提出来指正
|