本文首發於微信公衆號「後廠村碼農」前端
在2017年先後,RxJava一直很火,我在Android進階三部曲第一部《Android進階之光》中就介紹了RxJava的使用和原理。谷歌推出的LiveData和RxJava相似,也是基於觀察者,你能夠認爲LiveData是輕量級的RxJava。起初LiveData並不被看好,隨着谷歌的大力推廣,LiveData也慢慢的進入了你們的視野。通常來講,LiveData不多單獨使用,它更多的和Android Jetpack的其餘組件搭配使用,好比和ViewModel。這篇文章就來介紹LiveData的使用。java
LiveData如同它的名字同樣,是一個可觀察的數據持有者,和常規的observable不一樣,LiveData是具備生命週期感知的,這意味着它可以在Activity、Fragment、Service中正確的處理生命週期。 程序員
LiveData的數據源通常是ViewModel,也能夠是其它能夠更新LiveData的組件。當數據更新後,LiveData 就會通知它的全部觀察者,好比Activiy。與RxJava的方法不一樣的是,LiveData並非通知全部觀察者,它 只會通知處於Active狀態的觀察者,若是一個觀察者處於Paused或Destroyed狀態,它將不會收到通知。 這對於Activiy和Service特別有用,由於它們能夠安全地觀察LiveData對象而不用擔憂內存泄漏的問題。開發者也不須要在onPause或onDestroy方法中解除對LiveData的訂閱。還有一點須要注意的是一旦觀察者從新恢復Resumed狀態,它將會從新收到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
若是咱們想要在LiveData對象分發給觀察者以前對其中存儲的值進行更改,可使用Transformations.map()和Transformations.switchMap(),下面經過簡單的例子來說解它們。ide
若是想要在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
若是想要手動控制監聽其中一個的數據變化,並能根據須要隨時切換監聽,這時可使用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進階解密",達到了切換監聽的目的。
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進階之光
若是觀察者的生命週期處於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等技術,還有程序員成長類文章。