简介
开门见山,LiveData作为 Jetpack的组件之一,在项目中用到的频率已经越来越高了。
在谷歌官网上,关于 LiveData的介绍就简单贴一下:
LiveData is an observable data holder class.
Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services.
This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.
意思就是,有别于以前的 observable data,LiveData可以更好的感应 Acivity/Fragment生命周期的变化。使用 LiveData以下好处:
- 确保你的 UI 和你的数据状态一致
- 不会有内存泄露。因为 LiveData其实是绑定到 Lifecycle对象的。当LifeCycle生命周期走完时(通常情况下,是 onDestory),LiveData也会自动清理。
- 不会因 Activity的停止布奔溃
- 不需要手动去处理生命周期
- 始终保持最新的数据
- 数据/资源共享
- …
简单使用
通常情况下,使用 liveData需要以下几个步骤
- 创建一个 ViewModel,去持有 LiveData
- 创建一个 Observer,监听 LiveData的数据变化(observe(LifecycleOwner , observer)),这里需要一个LifecycleOwner,通常情况下是一个 Activity/Fragment/Service。
- 更新数据
创建一个 LiveData 对象
public class NameViewModel extends ViewModel {
// Create a LiveData with a String
private MutableLiveData<String> currentName;
public MutableLiveData<String> getCurrentName() {
if (currentName == null) {
currentName = new MutableLiveData<String>();
}
return currentName;
}
//
}
观察 LiveData对象
在官方文章里,是说在大多数情况下,在 OnCreate中创建 LiveData的观察者。个人认为也可以在 onResume生命周期中创建,前提是你得做一个初始化的判断(init = false)。
public class NameActivity extends AppCompatActivity {
private NameViewModel model;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other code to setup the activity...
// Get the ViewModel.
model = ViewModelProviders.of(this).get(NameViewModel.class);
// Create the observer which updates the UI.
final Observer<String> nameObserver = new Observer<String>() {
@Override
public void onChanged(@Nullable final String newName) {
// Update the UI, in this case, a TextView.
nameTextView.setText(newName);
}
};
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
model.getCurrentName().observe(this, nameObserver);
}
}
需要注意的是,通常情况下,LiveData仅在数据发生更改时才会发送更新。
更新数据
LiveData的两个更新数据的方法都是 protect的,所以我们通常使用的是他的子类
MutableLiveData,可以调用 setValue或者 postValue。
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String anotherName = "John Doe";
model.getCurrentName().setValue(anotherName);
}
});
注意:如果是在非UI线程中,请调用 postValue方法。
源码解析
setValue
其实LiveData的源码阅读起来还是比较简单的。我们可以从 setValue开始,走一遍调用流程,大概也就知道整个 LiveData的工作原理了。
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
可以看到,setValue方法主要是做了两个工作,一个是在 assertMainThread里判断该方法调用是否在主线程。
另一个其实就是将设置的 value进行分发。
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;
}
这个 dispatchingValue方法其实也比较简单,就是做一些判断,如果正在处理 value的发送,就返回。(这个主要是为了防止暴力点击)。最终会开始一个do{}while()循环,这个循环里,最终调用的是considerNotify方法。(mObservers对象是SafeIterableMap的一个实例,用来存放观察者对象,后面会说到。)
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
//
// we still first check observer.active to keep it as the entrance for events. So even if
// the observer moved to an active state, if we've not received that event, we better not
// notify for a more predictable notification order.
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
这个方法是重点,就是我们最终在监听的时候,收到的回调。我们一行行往下看。
mActive
这个判断的意思,就是 mActive 为 false,就返回了。那这个值怎么来的?
这个值是ObserverWrapper的一个成员变量,他是一个抽象类,在 LiveDate中,使用的是他的一个实现类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() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
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);
}
}
我们看一下onStateChanged方法。该方法其实是由LifecycleRegistry.addObserver方法发送出来的事件,其实,他的最上游,是个 Activity(ReportFragment,所以,才会对生命周期进行感应,具体的代码在ndroidx.lifecycle.ReportFragment)
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
也就是上面的 onStateChanged(owner,event)。我们回到onStateChange()方法。
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
可以看到,如果 owner的生命周期为DESTROYED时,会自动解绑,移除观察者对象,否则,就会调用父类ObserverWrapper中的activeStateChanged的代码。
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
if (mActive) {
dispatchingValue(this);
}
}
绕了一圈,终于看到了mActive了。可以看到,这个就是为 mActive赋值的方法了,而真正的 mActive的计算,其实是mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED)
。
这个其实就是枚举的比较,下面会说到。
shouldBeActive()
其实就是:
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
在 Lifecycle类下面有一个枚举类,定义了 Android的生命周期的几种状态,isAtLeast就是枚举的比较,比较简单。
observer.mLastVersion >= mVersion
这个其实没啥好说的,在 setValue时,会将mVersion + 1,那如果当前的版本号mVersion 比上一次操作的版本号都小,就不发送事件。
observe()
在 observe方法中,我们需要传入一个LifecycleOwner,一个是Observer,
看单词也明白,一个是生命周期的拥有者,一个就是观察者了。
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
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);
}
老规矩,如果不在主线程,报异常。如果生命周期都已经走到 DESTORYED ,直接返回。
然后就是刚才分析的LifecycleBoundObserver类了,通过这个类将 owner与observer绑定,通过 mObservers.putIfAbsent(observer, wrapper),将 observer的对像存到 map中,在前面dispatchingValue方法里取。
总结
LiveData的重要类有几个:
- LiveData,数据本身(这是废话)
- LifecycleBoundObserver 生命周期的监听,observer自动移除
- LifecycleOwner ,生命周期拥有者