概述
jetpack系列之Lifecycle
jetpack系列之LiveData
jetpack系列之Databinding
jetpack系列之Workmanager
一、LiveData概览
LiveData是一种可观察的数据持有者类。LiveData位于androidx.lifecycle包下,并具有生命周期感知能力,如感知Activity、Fragment 、Service等的生命周期。这种感知能力意味着使用时不需要手动处理生命周期,避免了内存泄漏等问题。
LiveData使用了观察者模式,当数据发生变化时LiveData会通知Observer完成界面更新,也就是数据驱动UI。如果观察者的生命周期处于STARED或RESUME状态,则LiveData会认为该观察者处于活跃状态。
二、从使用入手
LiveData使用非常简单,创建LiveData保存的info
数据和Observer对象,使用observe()方法将Observer
对象绑定到LiveData上
,Observer的onChanged方法会在数据改变时更新Textview。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView : TextView = findViewById(R.id.tv_textview)
MyLiveData.info.observe(this, object: Observer<String> {
override fun onChanged(t: String?) {
textView.text = t // 更新TextView
}
})
MyLiveData.info.observeForever(object: Observer<String> {
override fun onChanged(t: String?) {
textView.text = t // 更新TextView
}
})
//改变数据
MyLiveData.info.value = "主线程修改"
thread {
Thread.sleep(3000)
MyLiveData.info.postValue("子线程修改")
}
}
object MyLiveData {
val info: MutableLiveData<String> by lazy { MutableLiveData() }
}
可以看到LiveData有两种方法来绑定Observer对象,分别为observe()方法和observeForever()方法。两者有什么区别?
observe
observe()方法额外传入this也就是LifecycleOwner,这是因为在AppCompatActivity中父类实现了LifecycleOwner接口。这个LifecycleOwner参数相当于Lifecycle,是用来感知生命周期的关键,observe()方法内部会根据Lifecycle状态来处理,当Lifecycle处于活跃状态时才会回调到onChanged方法,相反则不会做任何事。
@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);
}
上面代码可以看到先做了一些稳定性判断,并保证Observer只添加一次,即一个Observer只允许和一个LifecycleOwner绑定。然后将LifecycleOwner和Observer重新包装了一层LifecycleBoundObserver,再添加到LifecycleRegistry,LifecycleRegistry相关可以看上一篇Lifecycle文章。接下来看看LifecycleBoundObserver
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
//Lifecycle 是STARTED 或者 RESUMED 状态时返回true
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
//DESTROYED时会移除mObserver
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
LifecycleBoundObserver间接实现了LifecycleObserver,所以生命周期发生变化时都会回调onStateChange()方法,该方法中判断宿主生命周期为DESTROYED时会移除mObserver,不需要用户手动去移除了;其他状态时会调用父类ObserverWrapper的activeStateChanged方法,如果生命周期为活跃状态,则会调用dispatchingValue方法,这个方法下文setValue再分析。
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
...
//注意这里参数为this
if (mActive) {
dispatchingValue(this);
}
}
observeForever
observeForever()方法没有关联LifecycleOwner,观察者会被视为始终处于活跃状态,因此生命周期不活跃时也会收到通知,也就会有内存泄漏的风险,这个跟Handler有点像。使用observeForever()还需要手动调用RemoveObserver()来移除Observer,不像oberve方法框架已经自动处理了。
public void observeForever(@NonNull Observer<? super T> observer) {
assertMainThread("observeForever");
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
wrapper.activeStateChanged(true);
}
private class AlwaysActiveObserver extends ObserverWrapper {
AlwaysActiveObserver(Observer<? super T> observer) {
super(observer);
}
@Override
boolean shouldBeActive() {
return true;
}
}
上面代码使用了AlwaysActiveObserver来包装Observer,它跟LifecycleBoundObserver一样都是ObserverWrapper的实现类,只不过shouldBeActive()方法直接
返回true,也没有生命周期变化监听,所以只要数据变化就会执行回调。
三、数据更新
LiveData没有公开更新数据的方法,我们一般使用它的子类MutableLiveData,该类对外提供了两个setValue()和
postValue()
方法,屏蔽了其他实现细节。一般在主线程使用setValue(),在子线程使用postValue(),
调用这两个方法都会触发观察者的onChange
()。
setValue
LiveData类中setValue()可以看到,该方法只能在主线程被调用。每次设置新value都会记录版本号mVersion++,然后调用dispatchingValue()
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
//注意这里传入null
dispatchingValue(null);
}
mDispatchingValue表示在正在向观察者分发新值,mDispatchInvalidated表示正在分发的新值是否失效,这两个布尔值实现了新旧值判断的逻辑。因为上面传入的initiator为null所以会走到else里,这里遍历所有注册的Observer逐个发送value,当value还未分发完外部又调用了setValue传进新值时,未分发的value将会被置为无效且重新分发新值。接下来看看最后一步considerNotify()
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
//正在分发新值
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//走到这里
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
//无效值舍弃
break;
}
}
}
} while (mDispatchInvalidated);
//新值分发结束
mDispatchingValue = false;
}
可以看到基本每个方法都会判断生命周期是否在活跃状态,时时刻刻获取Lifecycle生命周期以得到最新状态。这里的mVersion在setValue()中设置了递增,对应值从默认的-1变为0,而mLastVersion
用于标记 Observer内最后一个被回调的value的版本号默认值是-1,所以不满足if判断往下走调用sonChanged()方法,
流程到这就结束了。正常情况下mVersion值都是大于mLastVersion,
为了防止重复向某个观察者分发值,所以加了这个判断。
利用这个判断,我们可以用来处理LiveData的粘性事件。粘性事件即先发送事件,后订阅也能收到值,LiveData默认就是支持粘性事件传递的,很多时候我们不需要粘性事件。通过反射修改mLastVersion与
mVersion值相等,使代码不往下走,也就是旧值不分发即可实现关闭粘性事件。
private void considerNotify(ObserverWrapper observer) {
//判断是否活跃状态
if (!observer.mActive) {
return;
}
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//通知观察者的onChanged方法
observer.mObserver.onChanged((T) mData);
}
postValue
postValue()可以在子线程中调用,因此源码中加了个锁防止多线程竞争。其主要实现就是通过Handle切换到主线程,在Runnable中调用setValue()方法分发数据,剩下逻辑就跟setValue()一样。
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
//Handler切换到主线程去执行
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
setValue((T) newValue);
}
};
四、总结
1、LiveData主要是通过Lifecycle来感知生命周期;
2、LiveData 只会将更新通知给生命周期处于STARED或RESUME状态的观察者;
3、LiveData更新通知回调是在主线程执行的,因此只能在主线程中添加Observer;
3、LiveData类和ObserverWrapper
类都会持有一个value的版本号,数据只会分发给active且版本号不同的观察者;
最后
以上就是隐形柚子为你收集整理的Jetpack LiveData源码分析的全部内容,希望文章能够帮你解决Jetpack LiveData源码分析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复