[JetPack] LiveData源碼解析

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"1. 背景 ","attrs":{}},{"type":"link","attrs":{"href":"https://developer.android.com/topic/libraries/architecture/livedata#observelivedataobjects","title":""},"content":[{"type":"text","text":"官網LiveData","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    筆者在開發一款即時通訊和音視頻應用時,發現需要花費很大的力量去處理系統組件之間的數據傳遞,稍微有點不注意,就會出現狀態錯亂不同步的問題,影響用戶體驗,也給系統穩定性帶來了許多挑戰。因此,在我們2.0版本的重構過程中,毅然決定引入LiveData,經過實踐證明,其是一種優秀的解決方案,很適合處理此類問題,但也有一些細節需要注意,因此有了這篇文章,希望可以記錄下來。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1.1 定義","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"數據持有類","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"感知組件生命週期","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"數據能夠被觀察者所觀察","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1.2 使用 LiveData 的優勢","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"確保界面符合數據狀態","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不會發生內存泄漏","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不會因 Activity 停止而導致崩潰","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不再需要手動處理生命週期","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"數據始終保持最新狀態","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"適當的配置更改","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"共享資源","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2. 正文","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.1 使用 LiveData 步驟","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.1.1 創建 LiveData 實例以存儲某種類型的數據。這通常在 ViewModel 類中完成。","attrs":{}}]},{"type":"codeblock","attrs":{"lang":""},"content":[{"type":"text","text":"     public class NameViewModel extends ViewModel {\n\n        // Create a LiveData with a String\n        private MutableLiveData currentName;\n\n        public MutableLiveData getCurrentName() {\n            if (currentName == null) {\n                currentName = new MutableLiveData();\n            }\n            return currentName;\n        }\n\n        // Rest of the ViewModel...\n    }","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.1.2 創建可定義 onChanged() 方法的 Observer 對象,該方法可以控制當 LiveData 對象存儲的數據更改時會發生什麼。通常情況下,您可以在界面控制器(如 Activity 或 Fragment)中創建 Observer 對象。使用 observe() 方法將 Observer 對象附加到 LiveData 對象。observe() 方法會採用 LifecycleOwner 對象。這樣會使 Observer 對象訂閱 LiveData 對象,以使其收到有關更改的通知。通常情況下,您可以在界面控制器(如 Activity 或 Fragment)中附加 Observer 對象","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":""},"content":[{"type":"text","text":"    public class NameActivity extends AppCompatActivity {\n\n        private NameViewModel model;\n\n        @Override\n        protected void onCreate(Bundle savedInstanceState) {\n            super.onCreate(savedInstanceState);\n\n            // Other code to setup the activity...\n\n            // Get the ViewModel.\n            model = new ViewModelProvider(this).get(NameViewModel.class);\n\n            // Create the observer which updates the UI.\n            final Observer nameObserver = new Observer() {\n                @Override\n                public void onChanged(@Nullable final String newName) {\n                    // Update the UI, in this case, a TextView.\n                    nameTextView.setText(newName);\n                }\n            };\n\n            // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.\n            model.getCurrentName().observe(this, nameObserver);\n        }\n    }","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.1.3 更新 LiveData 對象,LiveData 沒有公開可用的方法來更新存儲的數據。MutableLiveData 類將公開 setValue(T) 和 postValue(T) 方法,如果您需要修改存儲在 LiveData 對象中的值,則必須使用這些方法。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":""},"content":[{"type":"text","text":"    button.setOnClickListener(new OnClickListener() {\n        @Override\n        public void onClick(View v) {\n            String anotherName = \"John Doe\";\n            model.getCurrentName().setValue(anotherName);\n        }\n    });","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.2 LiveData 代碼分析","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.2.1 MutableLiveData.java(LiveData的一個派生類,由於LiveData並未提供給外部更新數據的接口,所以一般使用MutableLiveData來實例化LiveData)","attrs":{}}]},{"type":"codeblock","attrs":{"lang":""},"content":[{"type":"text","text":"package androidx.lifecycle;\n\n/**\n * {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} method.\n *\n * @param The type of data hold by this instance\n */\n@SuppressWarnings(\"WeakerAccess\")\npublic class MutableLiveData extends LiveData {\n\n    /**\n     * Creates a MutableLiveData initialized with the given {@code value}.\n     *\n     * @param value initial value\n     */\n    public MutableLiveData(T value) {\n        super(value);\n    }\n\n    /**\n     * Creates a MutableLiveData with no value assigned to it.\n     */\n    public MutableLiveData() {\n        super();\n    }\n\n    @Override\n    public void postValue(T value) {\n        super.postValue(value);\n    }\n\n    @Override\n    public void setValue(T value) {\n        super.setValue(value);\n    }\n}","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.2.2 LiveData.observe()方法","attrs":{}}]},{"type":"codeblock","attrs":{"lang":""},"content":[{"type":"text","text":"    @MainThread // 標記該方法只允許在主線程運行,一般是在Activity/Service的onCreate方法中執行\n     // 第一個參數 LifecycleOwner,表示的是一個具有生命週期的通用組件,如Activity/Service\n     // 第二個參數 Observer,就是我們的觀察者實例,當數據變化時會執行onChange方法\n\n    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {\n        assertMainThread(\"observe\"); // 主線程斷言檢測\n        if (owner.getLifecycle().getCurrentState() == DESTROYED) { // 如果當前組件的生命週期是銷燬,則立即返回\n            // ignore\n            return;\n        }\n        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer); // 一個用於關聯 組件和觀察者 之間的對象\n        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);\n        if (existing != null && !existing.isAttachedTo(owner)) { // 不允許同一個觀察者觀察不同的組件\n            throw new IllegalArgumentException(\"Cannot add the same observer\"\n                    + \" with different lifecycles\");\n        }\n        if (existing != null) {\n            return;\n        }\n        owner.getLifecycle().addObserver(wrapper); // 添加到組件的觀察者隊列\n    }","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.2.3 注意事項:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"    我們看一段註釋,如果你已經post一個任務給主線程,但還未來得及執行,此時你再多次調用postValue,則意味着最新的值會被post,後面的值會覆蓋前面的值。這一點需要特別注意,筆者在開發的時候,由於在Service中根據網絡狀態來更新LiveData的值,但是發現Activity中部分值無法觀察到,後來看了註釋才煥然大悟。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":""},"content":[{"type":"text","text":"/**\n     * Posts a task to a main thread to set the given value. So if you have a following code\n     * executed in the main thread:\n     *
\n     * liveData.postValue(\"a\");\n     * liveData.setValue(\"b\");\n     * 
\n     * The value \"b\" would be set at first and later the main thread would override it with\n     * the value \"a\".\n     *

\n     * If you called this method multiple times before a main thread executed a posted task, only\n     * the last value would be dispatched.\n     *\n     * @param value The new value\n     */\n    protected void postValue(T value) {","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"3. 總結","attrs":{}}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文簡單介紹了JetPack組件中的一個話題,但不僅僅於此,未完待續,敬請期待。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章