LiveData學習使用
記錄一個在使用LiveData是遇到的有趣問題。由這個問題我們知道,在Activity中設置LiveData的Observer的時候,需要在onCreate中去設置。
起初些demo。主要是爲了驗證在SecondActivity,改變LiveData的值的時候,MainActivity的Observer何時被回調。
MainActivity代碼
SecondActivity的代碼
功能其實非常簡單,定義一個單例的LiveData對象,然後在SecondActivity中改變LiveData的值,看MainActivity中的Observer是否會回調。
結論是再沒有回到MainActivity的時候自然不會被回調,這個是符合預期的。
但是有一點我呢提,我發現回到MainActivity之後,居然執行了兩次回調。日誌如下。
怎麼回事呢,看了一下,我設置監聽是在onResume中,再次回到Main的時候又會設置一次監聽,但是值已經變化了啊,爲什麼還會被回調呢。那肯定就是在添加observer的時候還有些判斷,可以直接觸發回調。看下LiveData的observer源碼。
那就應該是標紅的這一行中有觸發回調的邏輯了。進到方法看一下。實際實現是在LifecycleRegistry.java中,代碼如下
public void addObserver(@NonNull LifecycleObserver observer) {
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
// 判斷這個observer對象是否已經被添加過了,所以如果不想重複觸發可以講傳入的observer設爲成員變量,後面講一下
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
if (previous != null) {
return;
}
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
// it is null we should be destroyed. Fallback quickly
return;
}
boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
// ** 重點就在於這個state的計算 ,下一段代碼就關於state的計算**
State targetState = calculateTargetState(observer);
mAddingObserverCounter++;
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
pushParentState(statefulObserver.mState);
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
popParentState();
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer);
}
if (!isReentrance) {
// we do sync only on the top level.
sync();
}
mAddingObserverCounter--;
}
private State calculateTargetState(LifecycleObserver observer) {
Entry<LifecycleObserver, ObserverWithState> previous = mObserverMap.ceil(observer);
State siblingState = previous != null ? previous.getValue().mState : null;
State parentState = !mParentStates.isEmpty() ? mParentStates.get(mParentStates.size() - 1)
: null;
return min(min(mState, siblingState), parentState);
}
按照現在的這種講Observer註冊寫道onResume中,LiveData被改變一次,只要Main沒有被Destroy,每次進入Main頁面都要走一次回調,這肯定是不行的。
根據源碼展示,有兩種方法,一種是在onCreate中註冊,其實這本就是標準用法。另一種方法是將observer對象設置爲成員變量(這一點我們可以從源碼中看到)。具體方法可以自己看看。
今天還看了一下Jetpack中的Room,結合LiveData使用,簡直是無敵了。過幾天也寫一下自己的理解。
總結
最近一直在找工作,因爲感覺在OPPO繼續待著,做的業務也沒啥意思了,很想做新模塊的開發,可是連續面了五家,全部倒再一面,我還是兩年前第一次找工作那樣,什麼問題我都能回答一些,但是往深了問就不知道了。兩年前憑藉面試表現,怎麼面試都能拿下offer,因爲當時作爲一個工作一年的人來說我所掌握的知識的廣度和深度,的確是比大部分人優秀的。但是現在我已經是一個工作三年的人了,對於基礎知識的深度還是和以前一樣,廣度甚至變小了。在OPPO一直是埋頭幹事情,對現有模塊添加一點東西,或者解決一些繁瑣的業務bug。不涉及架構設計能力的提升,也不用學習任何的新東西,我就完全能夠應付現有的工作需要。並且19年一整年,都是十點半以後下班的節奏,整個人都是非常疲憊的,接着就是完全忽略了對新技術的學習。也不再關注行業動態了。起先我一直都在埋怨OPPO這種沒有技術氛圍的工作環境,但是現在我才逐漸意識到,其實這些環境是一小部分因素,重點還是自己怎麼做。我的室友,作爲一名產品經理,每天比我回來的還晚,但是19年他看了大概有將近二十本書,並且大多數時候都是七點起牀去健身。時間是靠自己爭取的,知識也是靠自己汲取的。所以我覺得我需要重新開始好好學習一些非常好的東西。並且好好複習基礎知識,即使我還是沒辦法找到心儀的工作,即使我可能還要繼續留在OPPO,但是我一定會成爲更優秀的人,我要爲自己正名。