android LiveData原始碼分析--原始碼閱讀100天(2)
0.介紹
LiveData,同屬於JetPack構建集合,根據文件描述LiveData是一個可觀察的資料持有者類。與常規observable不同,LiveData是生命週期感知的,這意味著它尊重其他應用程式元件的生命週期,例如Activity,Fragment或Service。此感知確保LiveData僅更新處於活動生命週期狀態的應用程式元件觀察者。
優勢(以下摘自google文件,google翻譯了一下)
(1)確保您的UI符合您的資料狀態
LiveData遵循觀察者模式。生命週期狀態更改時,LiveData會通知Observer物件。您可以合併程式碼以更新這些Observer物件中的UI。每次應用程式資料更改時,您的觀察者都可以在每次更改時更新UI,而不是更新UI。
(2)沒有記憶體洩漏
觀察者繫結到Lifecycle物件並在其相關生命週期被破壞後自行清理。
由於停止活動而沒有崩潰
如果觀察者的生命週期處於非活動狀態(例如,在後端堆疊中的活動的情況下),則它不會接收任何LiveData事件。
(3)不再需要手動生命週期處理
UI元件只是觀察相關資料,不會停止或恢復觀察。 LiveData自動管理所有這些,因為它在觀察時意識到相關的生命週期狀態變化。
(4)始終保持最新資料
如果生命週期變為非活動狀態,則會在再次變為活動狀態時接收最新資料。例如,後臺活動在返回前臺後立即收到最新資料。
(5)適當的配置更改
如果由於配置更改(例如裝置輪換)而重新建立活動或片段,則會立即接收最新的可用資料。
(6)共享資源
您可以使用單例模式擴充套件LiveData物件以包裝系統服務,以便可以在應用程式中共享它們。 LiveData物件連線到系統服務一次,然後任何需要該資源的觀察者都可以只觀看LiveData物件。
1.使用
class MainActivity : AppCompatActivity() { val curName: MutableLiveData<String> by lazy { MutableLiveData<String>() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) curName.observe(this, Observer<String> { println("value is $it") }) curName.value="old value" } }
使用很簡單,當MutableLiveData物件的value發生改變時會出發Observer的onChanged方法,其中MutableLiveData繼承自LiveData。
2.目的
(1)LiveData如何進行生命週期感知
(2)如何更新事件
(3)如何避免記憶體洩漏
3.分析
3.1LiveData如何進行生命週期感知
先看一下LiveData的observer方法
@MainThread public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) { 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); }
看最後一行,owner.getLifecycle().addObserver(wrapper);owner就是咱們用的Activity或者Fragment,這就和上一篇文章Lifecycle對應上了
ofollow,noindex">android Lifecycle原始碼分析--原始碼閱讀100天(1) ,這裡新增的監聽者就是LifecycleBoundObservr,這個類實現了LifecycleObserver,這就是感應的生命週期的方式。
3.2如何更新事件
說實話,這個控制元件就是個觀察者模式,事件的Observer就是這個LifecycleBoundObserver,看看這個物件的onStateChanged方法
@Override public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) { if (mOwner.getLifecycle().getCurrentState() == DESTROYED) { removeObserver(mObserver); return; } activeStateChanged(shouldBeActive()); }
看一下activieStageChanged方法
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); } }
這個方法前面都是用來處理生命週期防止記憶體洩漏的,真正的用來觀察資料進行處理的就是dispatchingValue方法,看一下這個方法
private 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<T>, ObserverWrapper>> iterator = mObservers.iteratorWithAdditions(); iterator.hasNext(); ) { considerNotify(iterator.next().getValue()); if (mDispatchInvalidated) { break; } } } } while (mDispatchInvalidated); mDispatchingValue = false; }
如果ObserverWrapper引數不為null,就呼叫considerNotify方法,否則就遍歷mObservers,呼叫considerNotify,那就看一下這個方法
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); }
首先判斷ObserverWrapper是否需要被啟用,如果需要被啟用就呼叫activeStateChanged方法,否則就呼叫 我們自定義的Observer的onChanged((T) mData)方法。
3.3如何避免記憶體洩漏
回到onStateChanged的方法裡呼叫的activeStateChanged(shouldBeActive()),看一下shouldBeActive方法
@Override boolean shouldBeActive() { return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); } public boolean isAtLeast(@NonNull State state) { return compareTo(state) >= 0; }
這個方法就是將當前的state和STARTED進行對比,如果是STARTED或者RESUMED狀態,那麼傳入activeStateChanged的引數就是true,否則就是false,再回看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); } } }
當狀態沒有改變時,直接返回,否則根據newActive進行判斷是否為activt狀態,
if (wasInactive && mActive) { onActive(); } if (LiveData.this.mActiveCount == 0 && !mActive) { onInactive(); }
之後根據mActive和activeCount呼叫onActive和onInactive方法。這就一目瞭然了,當生命週期呼叫onStart之後,就處於啟用狀態,onstop之後就處於非啟用狀態,這樣資料改變時也就不會走到Observer的方法了,從而避免了記憶體洩漏。

image
關注我的公眾號