Jetpack 架構組件 LiveData ViewModel MD


Markdown版本筆記 我的GitHub首頁 我的博客 我的微信 我的郵箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

目錄

LiveData

官方文檔
官方公眾號介紹文章:正式發布 Android 架構組件 1.0 穩定版 | 附帶中文介紹視頻

LiveData 簡介

LiveData 是一個可被觀察的數據持有者類。與常規的Observable不同,LiveData能意識到應用程序組件的生命周期變化,這意味着它能遵守Activity、Fragment、Service等組件的生命周期。這種意識確保LiveData只更新處於活躍狀態的應用程序組件Observer。

如果一個Observer的生命周期處於STARTED或RESUMED狀態,那么LiveData將認為這個Observer處於活躍狀態。 LiveData僅通知活躍的Observer去更新UI。 非活躍狀態的Observer,即使訂閱了LiveData,也不會收到更新的通知。

結合一個實現了LifecycleOwner接口的對象,你能注冊一個Observer。這種結合關系使得當具有生命周期的對象的狀態變為DESTROYED時,Observer將被取消訂閱。 這對於Activity和Fragment尤其有用,因為它們可以安全地訂閱LiveData對象,而不必擔心內存泄漏 - 當Activity和Fragment生命周期為DESTROYED時,它們立即會被取消訂閱。

簡單地說,LiveData是一個數據持有類。它具有以下特點:

  • 數據可以被觀察者訂閱;
  • 能夠感知組件(Fragment、Activity、Service)的生命周期;
  • 只有在組件出於激活狀態(STARTED、RESUMED)才會通知觀察者有數據更新;

LiveData 功能概覽

LiveData 也是一個觀察者模型,但是它是一個與 Lifecycle 綁定了的 Subject,也就是說,只有當 UI 組件處於 ACTIVE 狀態時,它的 Observer 才能收到消息,否則會自動切斷訂閱關系,不用再像 RxJava 那樣通過 CompositeDisposable 來手動處理。

LiveData 的數據類似 EventBus 的 sticky event,不會被消費掉,只要有數據,它的 observer 就會收到通知。如果我們要把 LiveData 用作事件總線,還需要做一些定制,Github 上搜 SingleLiveEvent 可以找到源碼實現。

我們沒法直接修改 LiveData 的 value,因為它是不可變的(immutable),可變(mutable)版本是 MutableLiveData,通過調用 setValue(主線程)或 postValue(非主線程)可以修改它的 value。如果我們對外暴露一個 LiveData,但是不希望外部可以改變它的值,可以用如下技巧實現:

內部用 MutableLiveData ,可以修改值,對外暴露成 LiveData 類型,只能獲取值,不能修改值。

LiveData 有一個實現了中介者模式的子類 —— MediatorLiveData,它可以把多個 LiveData 整合成一個,只要任何一個 LiveData 有數據變化,它的觀察者就會收到消息。

綜上,我們匯總一下 LiveData 的使用場景:

  • LiveData - immutable 版本
  • MutableLiveData - mutable 版本
  • MediatorLiveData - 可匯總多個數據源
  • SingleLiveEvent - 事件總線

LiveData 只存儲最新的數據,雖然用法類似 RxJava2 的 Flowable,但是它不支持背壓(backpressure),所以不是一個流(stream),利用 LiveDataReactiveStreams 我們可以實現 Flowable 和 LiveData 的互換。

如果把異步獲取到的數據封裝成 Flowable,通過 toLiveData() 方法轉換成 LiveData,既利用了 RxJava 的線程模型,還消除了 Flowable 與 UI Controller 生命周期的耦合關系,借助 DataBinding 再把 LiveData 綁定到 xml UI 元素上,數據驅動 UI,妥妥的響應式。於是一幅如下模樣的數據流向圖就被勾勒了出來:

圖中右上角的 Local Data 是 AAC 提供的另一個強大武器 —— ORM 框架 Room。

LiveData 的優點

在項目中使用LiveData,會有以下優點:

  • 確保UI符合數據狀態:LiveData遵循觀察者模式。 當生命周期狀態改變時,LiveData會向Observer發出通知。 您可以把更新UI的代碼合並在這些Observer對象中。不必去考慮導致數據變化的各個時機,每次數據有變化,Observer都會去更新UI。
  • 沒有內存泄漏:Observer會綁定具有生命周期的對象,並在這個綁定的對象被銷毀后自行清理。
  • 不會因停止Activity而發生崩潰:如果Observer的生命周期處於非活躍狀態,例如在后退堆棧中的Activity,就不會收到任何LiveData事件的通知。
  • 不需要手動處理生命周期:UI組件只需要去觀察相關數據,不需要手動去停止或恢復觀察。LiveData會進行自動管理這些事情,因為在觀察時,它會感知到相應組件的生命周期變化。
  • 始終保持最新的數據:如果一個對象的生命周期變到非活躍狀態,它將在再次變為活躍狀態時接收最新的數據。 例如,后台Activity在返回到前台后立即收到最新數據。
  • 正確應對配置更改:如果一個Activity或Fragment由於配置更改(如設備旋轉)而重新創建,它會立即收到最新的可用數據。
  • 共享資源:您可以使用單例模式擴展LiveData對象並包裝成系統服務,以便在應用程序中進行共享。LiveData對象一旦連接到系統服務,任何需要該資源的Observer都只需觀察這個LiveData對象。

LiveData 使用步驟

按照以下步驟使用LiveData對象:

  • 創建一個LiveData的實例來保存特定類型的數據,這通常在ViewModel類中完成。
  • 創建一個定義了onChanged()方法的Observer對象,當LiveData對象保存的數據發生變化時,onChanged()方法可以進行相應的處理。您通常在UI控制器(如Activity或Fragment)中創建Observer對象。
  • 使用observe()方法將Observer對象注冊到LiveData對象。observe()方法還需要一個LifecycleOwner對象作為參數。Observer對象訂閱了LiveData對象,便會在數據發生變化時發出通知。您通常需要UI控制器(如Activity或Fragment)中注冊Observer對象。

Note:您可以使用observeForever(Observer)方法注冊一個沒有關聯LifecycleOwner對象的Observer。在這種情況下,Observer被認為始終處於活動狀態,因此當有數據變化時總是會被通知。您可以調用removeObserver(Observer)方法移除這些Observer。

當你更新LiveData對象中存儲的數據時,所有注冊了的Observer,只要所綁定的LifecycleOwner處於活動狀態,就會被觸發通知。

創建LiveData對象
LiveData是一個包裝器,可用於任何數據,包括實現Collections的對象,如List。一個LiveData對象通常存儲在ViewModel對象中,並通過getter方法訪問。

確保在ViewModel而不是Activity或Fragment中保存用來更新UI的LiveData對象,原因如下:

  • 避免臃腫的Activity和Fragment。這些UI控制器負責顯示數據而不是保存數據狀態
  • 將LiveData實例與特定Activity或Fragment實例分離,這將使得LiveData對象在配置更改后仍然存活。

觀察LiveData對象
在大多數情況下,出於以下原因,應用程序組件的onCreate()方法是開始觀察LiveData對象的最佳位置:

  • 確保系統不會從Activity或Fragment的onResume()方法中進行多余的調用。
  • 確保Activity或Fragment一旦變為活動狀態時,就有可展示的數據。當應用程序組件處於STARTED狀態,它就需從它所觀察的LiveData對象中接收到最新的值。所以我們需要在一開始就設置好觀察。

通常情況下,LiveData只在數據有變化時,給活躍的Observer進行通知。此行為的一個例外是,Observer在從非活躍狀態變為活躍狀態時也會收到通知。並且,如果Observer第二次從非活躍狀態變為活躍狀態,則只有在自上一次變為活躍狀態以來該數據發生變化時才會接收到更新。

更新LiveData對象
LiveData沒有公用的方法來更新存儲的數據,MutableLiveData類暴露公用的setValue(T)和postValue(T)方法,如果需要編輯存儲在LiveData對象中的值,必須使用這兩個方法。

通常在ViewModel中使用MutableLiveData,然后ViewModel僅向Observer公開不可變的LiveData對象。

Note: 必須要從主線程調用setValue(T) 方法來更新LiveData 對象,如果代碼在工作線程中執行, 你可以使用postValue(T) 方法來更新LiveData對象.

Transformations

您可能希望先轉換存儲在 LiveData 對象中的值,然后再將其分派給 Observer,或者您可能需要根據一個 LiveData 實例的值返回不同的 LiveData 實例。Lifecycle 包提供了 Transformations 類,提供了支持這些使用場景的方法。

要實現自己的轉換,您可以使用MediatorLiveData類,該類監聽其他LiveData對象並處理它們發出的事件。MediatorLiveData將其狀態正確地傳播到源LiveData對象。

map

map()使用一個函數來轉換存儲在LiveData對象中的值,並向下傳遞轉換后的值。

源碼

@MainThread
public static <X, Y> LiveData<Y> map(LiveData<X> source, final Function<X, Y> func) {
    final MediatorLiveData<Y> result = new MediatorLiveData<>(); //創建了一個中介者
    result.addSource(source, x -> result.setValue(func.apply(x))); //當源LiveData數據改變時通知中介,中介更改數據后通知觀察者
    return result; //返回的就是中介
}

Applies the given function on the main thread to each value emitted by source LiveData and returns LiveData, which emits resulting values.

將主線程上的給定函數應用於源LiveData發出的每個值,並返回發送結果值的LiveData。

The given function func will be executed on the main thread.

給定的函數func將在主線程上執行。

使用案例

Transformations.map(MyLiveData.get(), s -> 100 + s.length()) //使用map進行數據轉換
    .observe(this, i -> Log.i("bqt", "【觀察到的值】" + i));

switchMap

switchMap()與map()類似,不同的是,其要求傳遞給switchMap()的函數必須返回一個LiveData對象

switchMap主要會進行重新綁定的操作,如果從switchMapFunction中獲得的LiveData發生了變化,則會重新進行observe,從而避免上文提到的重復observe的問題

源碼

@MainThread
public static <X, Y> LiveData<Y> switchMap(LiveData<X> trigger, final Function<X, LiveData<Y>> func) {
    final MediatorLiveData<Y> result = new MediatorLiveData<>();
    result.addSource(trigger, new Observer<X>() {
        LiveData<Y> mSource;

        @Override
        public void onChanged(@Nullable X x) {
            LiveData<Y> newLiveData = func.apply(x); //轉換為新的源
            if (mSource == newLiveData) return; //和舊的源是同一個源,沒必要移除然后添加
            if (mSource != null) result.removeSource(mSource); //移除舊的源
            mSource = newLiveData;
            if (mSource != null) result.addSource(mSource, result::setValue); //添加新的源
        }
    });
    return result;
}

此機制允許較低級別的應用程序創建按需延遲計算的LiveData對象。ViewModel對象可以很容易地獲得對LiveData對象的引用,然后在其上定義轉換規則。

案例

Transformations.switchMap(MyLiveData.get(), s -> {
    MutableLiveData<Integer> liveData = ViewModelProviders.of(this).get(MyViewModel.class).getMutableLiveData();
    liveData.observe(this, i -> Log.i("bqt", "【觀察到的值1】" + i));
    liveData.setValue(1000 + new Random().nextInt(100));
    return liveData;
})
    .observe(this, i -> Log.i("bqt", "【觀察到的值2】" + i));

MediatorLiveData

我們從源碼中可以看到兩個方法都使用了MediatorLiveData<T>這個類型。這個類和MutableLiveData<T>一樣都繼承自LiveData<T>,主要是幫助我們解決這樣一種case:我們有多個LiveData實例,這些LiveData的value發生變更時都需要通知某一個相同的LiveData。

我們還可以在監聽value變化的過程中根據需要取消對某個LiveData的observe

LiveData subclass which may observe other LiveData objects and react on做出反應 OnChanged events from them. This class correctly正確地 propagates傳播 its active/inactive states down to source LiveData objects.

ViewModel

官方文檔
https://blog.csdn.net/qq_24442769/article/details/79426609

ViewModel類是被設計用來以可感知生命周期的方式存儲和管理 UI 相關數據,ViewModel中數據會一直存活即使 activity configuration發生變化,比如橫豎屏切換的時候。

implementation "android.arch.lifecycle:extensions:1.1.1" //ViewModelProviders 依賴
annotationProcessor "android.arch.lifecycle:compiler:1.1.1"

基本介紹

ViewModel類的設計目的是以一種關注生命周期的方式存儲和管理與UI相關的數據。

LiveData 是一個可以感知 Activity 、Fragment生命周期的數據容器。當 LiveData 所持有的數據改變時,它會通知相應的界面代碼進行更新。同時,LiveData 持有界面代碼 Lifecycle 的引用,這意味着它會在界面代碼(LifecycleOwner)的生命周期處於 started 或 resumed 時作出相應更新,而在 LifecycleOwner 被銷毀時停止更新。

不用手動控制生命周期,不用擔心內存泄露,數據變化時會收到通知。

ViewModel 將視圖的數據和邏輯從具有生命周期特性的實體(如 Activity 和 Fragment)中剝離開來,直到關聯的 Activity 或 Fragment 完全銷毀時,ViewModel 才會隨之消失,也就是說,即使在旋轉屏幕導致 Fragment 被重新創建等事件中,視圖數據依舊會被保留。ViewModels 不僅消除了常見的生命周期問題,而且可以幫助構建更為模塊化、更方便測試的用戶界面。

為Activity 、Fragment存儲數據,在當前Activity的Fragment之間實現數據共享

ViewModel職責是為Activity或Fragment管理、請求數據,具體數據請求邏輯不應該寫在ViewModel中,否則ViewModel的職責會變得太重,此處需要一個引入一個Repository,負責數據請求相關工作。



適用場景

  • ViewModel可以用於Activity內不同Fragment的交互,也可以用作Fragment之間一種解耦方式。
  • ViewModel也可以負責處理部分Activity/Fragment與應用其他模塊的交互。
  • ViewModel生命周期(以Activity為例)起始於Activity第一次onCreate(),結束於Activity最終finish時。

數據持久化

我們知道在屏幕旋轉的時候會經歷 activity 的銷毀與重新創建,這里就涉及到數據保存的問題,顯然重新請求或加載數據是不友好的。在 ViewModel 出現之前我們可以用 activity 的onSaveInstanceState()機制保存和恢復數據,但缺點很明顯,onSaveInstanceState只適合保存少量的可以被序列化、反序列化的數據,假如我們需要保存是一個比較大的 bitmap list ,這種機制明顯不合適。

使用ViewModel的話,ViewModel會自動保留之前的數據並給新的Activity或Fragment使用,直到當前Activity被系統銷毀時,Framework會調用ViewModel的onCleared()方法,我們可以在onCleared()方法中做一些資源清理操作。

由圖可知,ViewModel 生命周期是貫穿整個 activity 生命周期,包括 Activity 因旋轉造成的重創建,直到 Activity 真正意義上銷毀后才會結束。既然如此,用來存放數據再好不過了。

異步回調問題

通常我們 app 需要頻繁異步請求數據,比如調接口請求服務器數據。當然這些請求的回調都是相當耗時的,之前我們在 Activity 或 fragment里接收這些回調。所以不得不考慮潛在的內存泄漏情況,比如 Activity 被銷毀后接口請求才返回。處理這些問題,會給我們增添好多復雜的工作。

但現在我們利用 ViewModel 處理數據回調,可以完美的解決此痛點。

分擔 UI controller負擔

從最早的 MVC 到目前流行的 MVP、MVVM,目的無非是 明確職責,分離 UI controller 負擔。

UI controller 比如 Activity 、Fragment 是設計用來渲染展示數據、響應用戶行為、處理系統的某些交互。如果再要求他去負責加載網絡或數據庫數據,會讓其顯得臃腫和難以管理。所以為了簡潔、清爽、絲滑,我們可以分離出數據操作的職責給 ViewModel。

Fragments 間共享數據

比如在一個 Activity 里有多個fragment,這fragment 之間需要做某些交互。我之前的做法是接口回調,需要統一在 Activity 里管理,並且不可避免的 fragment 之間還得互相持有對方的引用。仔細想想就知道這是很翔的一件事,耦合度高不說,還需要大量的容錯判斷(比如對方的 fragment 是否還活着)。

使用ViewModel后會有如下好處:

  • Activity 不需要做任何事,甚至不知道這次交互,完美解耦。
  • Fragment 只需要與ViewModel交互,不需要知道對方 Fragment 的狀態甚至是否存在,更不需要持有其引用。所有當對方 Fragment 銷毀時,不影響本身任何工作。
  • Fragment 生命周期互不影響,甚至 fragment 替換成其他的 也不影響這個系統的運作。

ViewModel 的 onCleared 調用時機

ViewModel 有一個onCleared方法,那么他是在何時調用的呢?

public abstract class ViewModel {
    /**
     * This method will be called when this ViewModel is no longer used and will be destroyed.
     * It is useful when ViewModel observes some data and you need to clear this subscription to prevent a leak of this ViewModel.
     */
    @SuppressWarnings("WeakerAccess")
    protected void onCleared() {
    }
}

ViewModel 創建的時候提到過實例化了一個 HolderFragment 。並且實例化的時候通過上面 createHolderFragment 方法將其fragmentManager.beginTransaction().add(holder, HOLDER_TAG).commitAllowingStateLoss();,在 commit 之后,fragment 將會獲得生命周期。

我們看看其 onDestroy 方法:

@Override
public void onDestroy() {
    super.onDestroy();
    mViewModelStore.clear();
}

在HolderFragment的onDestroy()方法中調用了ViewModelStore.clear()方法,在該方法中會調用ViewModel的onCleared()方法:

/**
 *  Clears internal storage and notifies ViewModels that they are no longer used.
 */
public final void clear() {
    for (ViewModel vm : mMap.values()) {
        vm.onCleared(); //調用ViewMode的onCleared方法
    }
    mMap.clear();
}

Fragment 的 setRetainInstance 方法

Fragment具有屬性retainInstance,默認值為false,當設備旋轉時,fragment會隨托管activity一起銷毀並重建。

調用setRetainInstance(true)方法可保留fragment,已保留的fragment不會隨着activity一起被銷毀,相反,它會一直保留(進程不消亡的前提下),並在需要時原封不動地傳遞給新的Activity。

保留Fragment的原理

當設備配置發生變化時,FragmentManager首先銷毀隊列中fragment的視圖(因為可能有更合適的匹配資源),緊接着,FragmentManager將檢查每個fragment的retainInstance屬性值。

  • 如果retainInstance屬性值為false,FragmentManager會立即銷毀該fragment實例,隨后,為適應新的設備配置,新的Activity的新的FragmentManager會創建一個新的fragment及其視圖。
  • 如果retainInstance屬性值為true,則該fragment本身不會被銷毀。為適應新的設備配置,當新的Activity創建后,新的FragmentManager會找到被保留的fragment,並重新創建其視圖(而不會重建fragment本身)。

雖然保留的fragment沒有被銷毀,但它已脫離消亡中的activity並處於保留狀態。盡管此時的fragment仍然存在,但已經沒有任何activity托管它。

需要說明的是,只有調用了fragment的setRetainInstance(true)方法,並且因設備配置改變,托管Activity正在被銷毀的條件下,fragment才會短暫的處於保留狀態。如果activity是因操作系統需要回收內存而被銷毀,則所有的fragment也會隨之銷毀。

那么問題來了,為什么橫豎屏切換 ViewModel 不會回調 onCleared?
看 HolderFragment 的構造方法里有個setRetainInstance(true);

public HolderFragment() {
    setRetainInstance(true);
}

setRetainInstance(boolean) 是Fragment中的一個方法。將這個方法設置為true就可以使當前Fragment在Activity重建時存活下來。在setRetainInstance(boolean)為true的 Fragment 中放一個專門用於存儲ViewModel的Map, 自然Map中所有的ViewModel都會幸免於Activity重建,讓Activity, Fragment都綁定一個這樣的Fragment, 將ViewModel存放到這個 Fragment 的 Map 中, ViewModel 組件就這樣實現了。

使用案例

MutableLiveData 簡單使用案例

LiveData which publicly exposes公開暴露 setValue(T) and postValue(T) method.
將 LiveData 的 setValue 和 postValue 訪問權限修改為了 public

public class MutableLiveData<T> extends LiveData<T> 

案例一:直接在Activity中定義LiveData
這種方式不推薦

MutableLiveData<String> liveData = new MutableLiveData<>(); //定義LiveData
liveData.observe(this, s -> tvTitle.setText("值為:" + s)); //將Observer對象注冊到LiveData對象
liveData.setValue(value);//修改LiveData存儲的值會立即觸發onChanged()回調
new Thread(() -> liveData.postValue(value)).start(); //在子線程必須使用 postValue

調用observe()之后,將立即回調onChanged(),提供存儲在LiveData中的最新值。如果LiveData對象存儲的值並未設置,則不調用onChanged()。
當通過setValue修改LiveData存儲的值時,會立即回調onChanged()方法。
在主線程可以使用setValue也可以使用postValue,但在子線程必須使用postValue,否則報llegalStateException: Cannot invoke

案例二:和ViewModel結合使用
定義ViewModel:

public class MyViewModel extends ViewModel {
    private MutableLiveData<String> mCurrentName;

    public MutableLiveData<String> getCurrentName() {
        if (mCurrentName == null) {
            mCurrentName = new MutableLiveData<>();
        }
        return mCurrentName;
    }
}
MyViewModel mModel = ViewModelProviders.of(this).get(MyViewModel.class); //Google推薦的方式
mModel.getCurrentName().observe(this, s -> tvTitle.setText("值為:" + s));
mModel.getCurrentName().setValue(value);

案例三:和單例模式結合使用
定義LiveData:

public class MyMutableLiveData extends MutableLiveData<String> {

    private MyMutableLiveData() {
    }

    public static MyMutableLiveData get() {
        return SingleHolder.INSTANCE;
    }

    private static class SingleHolder {
        private static final MyMutableLiveData INSTANCE = new MyMutableLiveData();
    }
}
MyMutableLiveData.get().observe(this, s -> tvTitle.setText("值為:" + s));
MyMutableLiveData.get().setValue(value);

擴展 LiveData

LiveData

public class MyLiveData extends LiveData<String> {
    private Manager manager;
    private OnChangeListener listener = time -> postValue("回調值:" + time); //因為在子線程中,所以一定要用postValue

    private MyLiveData() {
        manager = new Manager();
    }

    public static MyLiveData get() {
        return SingleHolder.INSTANCE;
    }

    private static class SingleHolder {
        private static final MyLiveData INSTANCE = new MyLiveData();
    }

    @Override
    protected void onActive() {
        super.onActive();
        Log.i("bqt", "【onActive】");
        manager.addListerner(listener);
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        Log.i("bqt", "【onInactive】");
        manager.removeListerner(listener);
    }
}

Manager

public class Manager {
    private boolean stop = false;
    private Set<OnChangeListener> listeners = new HashSet<>();

    public Manager() {
        new Thread(() -> {
            while (!stop) {
                SystemClock.sleep(2000);
                for (OnChangeListener listener : listeners) {
                    String time = new SimpleDateFormat("HH:mm:ss SSS", Locale.getDefault()).format(new Date());
                    listener.onChanged(time);
                }
            }
        }).start();
    }

    public void addListerner(OnChangeListener listener) {
        listeners.add(listener);
    }

    public void removeListerner(OnChangeListener listener) {
        listeners.remove(listener);
    }

    public void stop() {
        stop = true;
    }
}

案例說明

回調接口

public interface OnChangeListener {
    void onChanged(String time);
}

本例中LiveData的實現包括以下重要的方法:

  • 當LiveData對象有一個活躍的Observer時,onActive()方法被調用,這意味着你需要從這個方法開始觀察Manager的更新。
  • 當LiveData對象沒有任何活躍的Observer時,onInactive()方法被調用,由於沒有Observer在監聽,所以沒有理由繼續保持與Manager的連接。
  • setValue(T)方法更新LiveData實例的值,並通知活動觀察者有關更改。
MyLiveData.get().observe(this, s -> Log.i("bqt", "【觀察到的值】" + s));

observe()方法第一個參數是作為LifecycleOwner實例的Fragment或FragmentActivity,這樣做表示此Observer綁定了Lifecycle對象的生命周期,即:

  • 如果Lifecycle對象不處於活動狀態,則即使值發生更改,也不會調用Observer。
  • Lifecycle對象被銷毀后,Observer被自動刪除。
  • LiveData對象具有感知生命周期的能力,意味着您可以在多個Activity,Fragment和service之間共享它們。

MediatorLiveData 案例

public class MyMediatorLiveData extends MediatorLiveData<String> {
    @Override
    protected void onActive() {
        super.onActive();
        Log.i("bqt", "【onActive】");
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        Log.i("bqt", "【onInactive】");
    }
}

添加源

MyMediatorLiveData mediatorLiveData = new MyMediatorLiveData();
mediatorLiveData.addSource(liveData1, s -> mediatorLiveData.setValue("liveData1-" + s));
mediatorLiveData.addSource(liveData2, s -> mediatorLiveData.setValue("liveData2-" + s));
mediatorLiveData.observe(this, s -> tvTitle.setText("值為:" + s));

在源LiveData數據變更后MediatorLiveData注冊的觀察者就會收到通知。

liveData1.postValue(value1);
liveData2.setValue(value2);

ViewModel 案例

定義 ViewModel

public class MyViewModel extends ViewModel {
    private MutableLiveData<String> mutableLiveData;

    public MutableLiveData<String> getMutableLiveData() {
        if (mutableLiveData == null) {
            mutableLiveData = new MutableLiveData<>();
        }
        return mutableLiveData;
    }
}

通過ViewModelProviders獲取 ViewModel 實例

MyViewModel model = ViewModelProviders.of(activity).get(MyViewModel.class);
MyViewModel model = ViewModelProviders.of(fragment).get(MyViewModel.class); 
MyViewModel model = ViewModelProviders.of(activity,factory).get(MyViewModel.class);

You usually request a ViewModel the first time the system calls an activity object's onCreate() method.

在Activity中使用

private MyViewModel mModel;
mModel = ViewModelProviders.of(this).get(MyViewModel.class); //獲取ViewModel實例,注意這里的【this】
mModel.getMutableLiveData().observe(this, s -> tvTitle.setText("Activity獲取到的值為:" + s)); //注冊觀察者
mModel.getMutableLiveData().setValue(value); //修改LiveData中存儲的值

在Fragment中使用

private MyViewModel mModel;
mModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class); //注意這里一定要用【getActivity()】
mModel.getMutableLiveData().observe(this, s -> tv.setText("Fragment獲取到的值為:" + s));
mModel.getMutableLiveData().setValue(value);

2019-3-29


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM