前言
本篇文章主要講解LiveData工作的原理逛绵,如果還不知道LiveData如何用的話欧引,請(qǐng)參考官方文檔频伤。
LiveData的講解涉及到了Lifecycle的知識(shí),如果你還不了解LifeCycle芝此,請(qǐng)參考文檔LifeCycle介紹憋肖。
介紹
LiveData是一個(gè)數(shù)據(jù)持有類因痛,它可以通過添加觀察者被其他組件觀察其變更。不同于普通的觀察者岸更,它最重要的特性就是遵從應(yīng)用程序的生命周期鸵膏,如在Activity中如果數(shù)據(jù)更新了但Activity已經(jīng)是destroy狀態(tài),LivaeData就不會(huì)通知Activity(observer)怎炊。當(dāng)然谭企。LiveData的優(yōu)點(diǎn)還有很多,如不會(huì)造成內(nèi)存泄漏等评肆。
LiveData通常會(huì)配合ViewModel來使用债查,ViewModel負(fù)責(zé)觸發(fā)數(shù)據(jù)的更新,更新會(huì)通知到LiveData瓜挽,然后LiveData再通知活躍狀態(tài)的觀察者攀操。
原理分析
下面直接看代碼:
public class UserProfileViewModel extends ViewModel {
private String userId;
private MutableLiveData<User> user;
private UserRepository userRepo;
public void init(String userId) {
this.userId = userId;
userRepo = new UserRepository();
user = userRepo.getUser(userId);
}
public void refresh(String userId) {
user = userRepo.getUser(userId);
}
public MutableLiveData<User> getUser() {
return user;
}
}
上面UserProfileViewModel內(nèi)部持有 UserRepository 中 MutableLiveData<User>的引用,并且提供了獲取 MutableLiveData 的方法 getUser()秸抚,UserRepository 負(fù)責(zé)從網(wǎng)絡(luò)或數(shù)據(jù)庫中獲取數(shù)據(jù)并封裝成 MutableLiveData 然后提供給 ViewModel速和。
我們?cè)?UserProfileFragment 中為 MutableLiveData<User> 注冊(cè)觀察者,如下:
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String userId = getArguments().getString(UID_KEY);
viewModel = ViewModelProviders.of(this).get(UserProfileViewModel.class);
viewModel.init(userId);
//標(biāo)注1
viewModel.getUser().observe(UserProfileFragment.this, new Observer<User>() {
@Override
public void onChanged(@Nullable User user) {
if (user != null) {
tvUser.setText(user.toString());
}
}
});
}
看標(biāo)注1處剥汤,viewModel.getUser()獲取到 MutableLiveData<User> 也就是我們的 LiveData颠放,然后調(diào)用 LiveData的observer方法,并把UserProfileFragment作為參數(shù)傳遞進(jìn)去吭敢。observer() 方法就是我們分析的入口了碰凶,接下來我們看LiveData的observer()方法都做了什么:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
//標(biāo)注1
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//標(biāo)注2
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);
}
可以看到,UserProfileFragment 是作為 LifeCycleOwner 參數(shù)傳進(jìn)來的鹿驼,如果你的support包版本大于等于26.1.0欲低,support包中的 Fragment 會(huì)默認(rèn)繼承自 LifecycleOwner,而 LifecycleOwner 可獲取到該組件的 LifeCycle畜晰,也就知道了 UserProfileFragment 組件的生命周期(在這里默認(rèn)大家已經(jīng)了解過LifeCycle了)砾莱。
看標(biāo)注1處,如果我們的 UserProfileFragment 組件已經(jīng)是destroy狀態(tài)的話凄鼻,將直接返回腊瑟,不會(huì)被加入觀察者行列。如果不是destroy狀態(tài)块蚌,就到標(biāo)注2處闰非,新建一個(gè) LifecycleBoundObserver 將我們的 LifecycleOwner 和 observer保存起來,然后調(diào)用 mObservers.putIfAbsent(observer, wrapper) 將observer和wrapper分別作為key和value存入Map中峭范,putIfAbsent()方法會(huì)判斷如果 value 已經(jīng)能夠存在财松,就返回,否則返回null纱控。
如果返回existing為null辆毡,說明以前沒有添加過這個(gè)觀察者政敢,就將 LifecycleBoundObserver 作為 owner 生命周期的觀察者,也就是作為 UserProfileFragment 生命周期的觀察者胚迫。
我們看下LifecycleBoundObserver 源碼:
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<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);
}
}
代碼并不多喷户,LifecycleBoundObserver 繼承自 ObserverWrapper 并實(shí)現(xiàn)了 GenericLifecycleObserver接口,而 GenericLifecycleObserver 接口又繼承自 LifecycleObserver 接口访锻,那么根據(jù) Lifecycle 的特性褪尝,實(shí)現(xiàn)了LifecycleObserver接口并且加入 LifecycleOwner 的觀察者里就可以感知或主動(dòng)獲取 LifecycleOwner 的狀態(tài)。
好了期犬,看完了觀察者河哑,那么我們的LiveData什么時(shí)候會(huì)通知觀察者呢?不用想龟虎,肯定是數(shù)據(jù)更新的時(shí)候璃谨,而數(shù)據(jù)的更新是我們代碼自己控制的,如請(qǐng)求網(wǎng)絡(luò)返回User信息后鲤妥,我們會(huì)主動(dòng)將User放入MutableLiveData中佳吞,這里我在UserRepository中直接模擬網(wǎng)絡(luò)請(qǐng)求如下:
public class UserRepository {
final MutableLiveData<User> data = new MutableLiveData<>();
public MutableLiveData<User> getUser(final String userId) {
if ("xiasm".equals(userId)) {
data.setValue(new User(userId, "夏勝明"));
} else if ("123456".equals(userId)) {
data.setValue(new User(userId, "哈哈哈"));
} else {
data.setValue(new User(userId, "unknow"));
}
return data;
}
}
當(dāng)調(diào)用getUser()方法的時(shí)候,我們調(diào)用MutableLiveData的setValue()方法將數(shù)據(jù)放入LiveData中棉安,這里MutableLiveData實(shí)際上就是繼承自LiveData底扳,沒有什么特別:
public class MutableLiveData<T> extends LiveData<T> {
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
setValue()在放入U(xiǎn)ser的時(shí)候必須在主線程,否則會(huì)報(bào)錯(cuò)贡耽,而postValue則沒有這個(gè)檢查衷模,而是會(huì)把數(shù)據(jù)傳入到主線程。我們直接看setValue()方法:
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
首先調(diào)用assertMainThread()檢查是否在主線程蒲赂,接著將要更新的數(shù)據(jù)賦給mData阱冶,然后調(diào)用 dispatchingValue()方法并傳入null,將數(shù)據(jù)分發(fā)給各個(gè)觀察者滥嘴,如我們的 UserProfileFragment木蹬。看 dispatchingValue()方法實(shí)現(xiàn):
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
//標(biāo)注1
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//標(biāo)注2
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
從標(biāo)注1可以看出氏涩,dispatchingValue()參數(shù)傳null和不傳null的區(qū)別就是如果傳null將會(huì)通知所有的觀察者届囚,反之僅僅通知傳入的觀察者有梆。我們直接看標(biāo)注2是尖,通知所有的觀察者通過遍歷 mObservers ,將所有的 ObserverWrapper 拿到泥耀,實(shí)際上就是我們上面提到的 LifecycleBoundObserver饺汹,通知觀察者調(diào)用considerNotify()方法,這個(gè)方法就是通知的具體實(shí)現(xiàn)了痰催。
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);
}
如果觀察者不是活躍狀態(tài)兜辞,將不會(huì)通知此觀察者迎瞧,看最后一行,observer.mObserver.onChanged((T) mData)逸吵,observer.mObserver就是我們調(diào)用LiveData的observer()方法傳入的 Observer凶硅,然后調(diào)用 Observer 的 onChanged((T) mData)方法,將保存的數(shù)據(jù)mData傳入扫皱,也就實(shí)現(xiàn)了更新足绅。在看下我們實(shí)現(xiàn)的Observer:
viewModel.getUser().observe(UserProfileFragment.this, new Observer<User>() {
@Override
public void onChanged(@Nullable User user) {
if (user != null) {
tvUser.setText(user.toString());
}
}
});
如果哪個(gè)控件要根據(jù)user的變更而及時(shí)更新,就在onChanged()方法里處理就可以了韩脑。到這里氢妈,LiveData已經(jīng)能夠分析完了,其實(shí)LiveData的實(shí)現(xiàn)還是要依賴于Lifecycle段多。