Android Jetpack架構組件(四)一文帶你瞭解LiveData(使用篇)

本文首發於微信公衆號「後廠村碼農」前端

前言

在2017年先後,RxJava一直很火,我在Android進階三部曲第一部《Android進階之光》中就介紹了RxJava的使用和原理。谷歌推出的LiveData和RxJava相似,也是基於觀察者,你能夠認爲LiveData是輕量級的RxJava。起初LiveData並不被看好,隨着谷歌的大力推廣,LiveData也慢慢的進入了你們的視野。通常來講,LiveData不多單獨使用,它更多的和Android Jetpack的其餘組件搭配使用,好比和ViewModel。這篇文章就來介紹LiveData的使用。java

1.什麼是LiveData

LiveData如同它的名字同樣,是一個可觀察的數據持有者,和常規的observable不一樣,LiveData是具備生命週期感知的,這意味着它可以在Activity、Fragment、Service中正確的處理生命週期。 程序員

mv4Y9I.png
LiveData的數據源通常是ViewModel,也能夠是其它能夠更新LiveData的組件。當數據更新後,LiveData 就會通知它的全部觀察者,好比Activiy。與RxJava的方法不一樣的是,LiveData並非通知全部觀察者,它 只會通知處於Active狀態的觀察者,若是一個觀察者處於Paused或Destroyed狀態,它將不會收到通知。 這對於Activiy和Service特別有用,由於它們能夠安全地觀察LiveData對象而不用擔憂內存泄漏的問題。開發者也不須要在onPause或onDestroy方法中解除對LiveData的訂閱。還有一點須要注意的是一旦觀察者從新恢復Resumed狀態,它將會從新收到LiveData的最新數據。

1.LiveData的基本用法

LiveData是一個抽象類,它的最簡單的實現類爲MutableLiveData,這裏舉個最簡單的例子。安全

public class MainActivity extends AppCompatActivity {
   private static final String TAG="MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MutableLiveData<String> mutableLiveData  = new MutableLiveData<>();
        mutableLiveData.observe(this, new Observer<String>() {//1
            @Override
            public void onChanged(@Nullable final String s) {
                Log.d(TAG, "onChanged:"+s);
            }
        });
        mutableLiveData.postValue("Android進階三部曲");//2
    }
}

複製代碼

註釋1處的observe方法有兩個參數分別是LifecycleOwner和 Observer<T> ,第一個參數就是MainActivity自己,第二個參數新建了一個Observer<String>,在onChanged方法中獲得回調。註釋處的postValue方法會在主線程中更新數據,這樣就會獲得打印的結果。 D/MainActivity: onChanged:Android進階三部曲微信

在大多數狀況下,LiveData的observe方法會放在onCreate方法中,若是放在onResume方法中,會出現屢次調用的問題。除了MutableLiveData的postValue方法,還可使用setValue方法,它們以前的區別是,setValue方法必須在主線程使用,若是是在工做線程中更新LiveData,則可使用postValue方法。app

2.更改LiveData中的數據

若是咱們想要在LiveData對象分發給觀察者以前對其中存儲的值進行更改,可使用Transformations.map()和Transformations.switchMap(),下面經過簡單的例子來說解它們。ide

2.1 Transformations.map()

若是想要在LiveData對象分發給觀察者以前對其中存儲的值進行更改,可使用Transformations.map()。post

public class MainActivity extends AppCompatActivity {
   private static final String TAG="MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MutableLiveData<String> mutableLiveData  = new MutableLiveData<>();
        mutableLiveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String s) {
                Log.d(TAG, "onChanged1:"+s);
            }
        });
        LiveData transformedLiveData =Transformations.map(mutableLiveData, new Function<String, Object>() {
            @Override
            public Object apply(String name) {
               return name + "+Android進階解密";
            }
        });
        transformedLiveData.observe(this, new Observer() {
            @Override
            public void onChanged(@Nullable Object o) {
                Log.d(TAG, "onChanged2:"+o.toString());
            }
        });
        mutableLiveData.postValue("Android進階之光");
    }
}
複製代碼

經過Transformations.map(),在mutableLiveData的基礎上又加上了字符串"+Android進階解密"。 打印結果爲: D/MainActivity: onChanged1:Android進階之光 D/MainActivity: onChanged2:Android進階之光+Android進階解密this

2.2 Transformations.switchMap()

若是想要手動控制監聽其中一個的數據變化,並能根據須要隨時切換監聽,這時可使用Transformations.switchMap(),它和Transformations.map()使用方式相似,只不過switchMap()必須返回一個LiveData對象。spa

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    MutableLiveData<String> mutableLiveData1;
    MutableLiveData<String> mutableLiveData2;
    MutableLiveData<Boolean> liveDataSwitch;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mutableLiveData1 = new MutableLiveData<>();
        mutableLiveData2 = new MutableLiveData<>();
        liveDataSwitch = new MutableLiveData<Boolean>();//1

        LiveData transformedLiveData= Transformations.switchMap(liveDataSwitch, new Function<Boolean, LiveData<String>>() {
            @Override
            public LiveData<String> apply(Boolean input) {
                if (input) {
                    return mutableLiveData1;
                } else {
                    return mutableLiveData2;
               }
            }
        });

        transformedLiveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String s) {
                Log.d(TAG, "onChanged:" + s);
            }
        });
        liveDataSwitch.postValue(false);//2
        mutableLiveData1.postValue("Android進階之光");
        mutableLiveData2.postValue("Android進階解密");
    }
}
複製代碼

註釋1處新建一個MutableLiveData<Boolean>()來控制切換並賦值給liveDataSwitch,當liveDataSwitch的值爲true時返回mutableLiveData1,不然返回mutableLiveData2。註釋2處將liveDataSwitch的值更新爲false,這樣輸出的結果爲"Android進階解密",達到了切換監聽的目的。

3 合併多個LiveData數據源

MediatorLiveData繼承自mutableLiveData,它能夠將多個LiveData數據源集合起來,能夠達到一個組件監聽多個LiveData數據變化的目的。

public class MainActivity extends AppCompatActivity {
   private static final String TAG="MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MutableLiveData<String> mutableLiveData1  = new MutableLiveData<>();
        MutableLiveData<String> mutableLiveData2  = new MutableLiveData<>();
        MediatorLiveData liveDataMerger = new MediatorLiveData<String>();
        liveDataMerger.addSource(mutableLiveData1, new Observer() {
            @Override
            public void onChanged(@Nullable Object o) {
                Log.d(TAG, "onChanged1:"+o.toString());
            }
        });

        liveDataMerger.addSource(mutableLiveData2, new Observer() {
            @Override
            public void onChanged(@Nullable Object o) {
                Log.d(TAG, "onChanged2:"+o.toString());
            }
        });
        liveDataMerger.observe(this, new Observer() {
            @Override
            public void onChanged(@Nullable Object o) {
                Log.d(TAG, "onChanged:"+o.toString());
            }
        });
        mutableLiveData1.postValue("Android進階之光");
    }
}
複製代碼

爲了更直觀的舉例,將LiveData和MediatorLiveData放到了同一個Activity中。經過MediatorLiveData的addSource將兩個MutableLiveData合併到一塊兒,這樣當任何一個MutableLiveData數據發生變化時,MediatorLiveData均可以感知到。

打印的結果爲: D/MainActivity: onChanged1:Android進階之光

4 拓展LiveData對象

若是觀察者的生命週期處於STARTED或RESUMED狀態,LiveData會將觀察者視爲處於Active狀態 。關於如何擴展LiveData,官網的例子是比較簡潔的,以下所示。

public class StockLiveData extends LiveData<BigDecimal> {
    private static StockLiveData sInstance;
    private StockManager stockManager;

    private SimplePriceListener listener = new SimplePriceListener() {
        @Override
        public void onPriceChanged(BigDecimal price) {
            setValue(price);
        }
    };

    @MainThread
    public static StockLiveData get(String symbol) {
        if (sInstance == null) {
            sInstance = new StockLiveData(symbol);
        }
        return sInstance;
    }

    private StockLiveData(String symbol) {
        stockManager = new StockManager(symbol);
    }

    @Override
    protected void onActive() {
        stockManager.requestPriceUpdates(listener);
    }

    @Override
    protected void onInactive() {
        stockManager.removeUpdates(listener);
    }
}
複製代碼

上面的代碼是一個觀察股票變更的一個例子,對LiveData進行了拓展,實現了LiveData的兩個空方法onActive和onInactive。當Active狀態的觀察者的數量從0變爲1時會調用onActive方法,通俗來說,就是當LiveData對象具備Active狀態的觀察者時調用onActive方法,應該在onActive方法中開始觀察股票價格的更新。當LiveData對象沒有任何Active狀態的觀察者時調用onInactive方法,在這個方法中,斷開與StockManager服務的鏈接。

在Fragment中使用StockLiveData,以下所示。

public class MyFragment extends Fragment {
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        StockLiveData.get(symbol).observe(this, price -> {
            // Update the UI.
        });
    }
}
複製代碼

總結

這篇文章主要介紹了什麼是LiveData,以及LiveData的使用方法,這裏沒有介紹LiveData和ViewModel的結合使用,以及LiveData的原理,這些會在後面的文章進行介紹。

更多的內容請關注個人獨立博客的知識體系:
liuwangshu.cn/system/


這裏不只分享大前端、Android、Java等技術,還有程序員成長類文章。

相關文章
相關標籤/搜索