1、概述
LiveData是一種可觀察的數(shù)據(jù)存儲(chǔ)器類(lèi),LiveData使用觀察者模式,每當(dāng)數(shù)據(jù)發(fā)生變化時(shí),LiveData會(huì)通知 Observer對(duì)象,我們可以在這些 Observer 對(duì)象中更新UI
ViewModel對(duì)象為特定的界面組件(如 Fragment 或 Activity)提供數(shù)據(jù),并包含數(shù)據(jù)處理業(yè)務(wù)邏輯,會(huì)配合LiveData一起使用
接下來(lái),我們會(huì)先介紹如果使用LiveData,并編寫(xiě)一個(gè)LiveData Demo,接著再結(jié)合ViewModel對(duì)LiveData Demo的代碼進(jìn)行重構(gòu)
2、LiveData使用說(shuō)明
LiveData<T>是一個(gè)抽象類(lèi),它有2個(gè)子類(lèi)分別是:MutableLiveData<T>和MediatorLiveData<T>,在編寫(xiě)代碼時(shí),是創(chuàng)建的子類(lèi)。我們先來(lái)看MutableLiveData<T>使用方法,在后面的示例中再介紹如何使用MediatorLiveData<T>
2.1、創(chuàng)建LiveData對(duì)象
如果我們要觀察的對(duì)象類(lèi)為String,就通過(guò)如下代碼創(chuàng)建一個(gè)MutableLiveData對(duì)象
MutableLiveData<String> liveData = new MutableLiveData<>();
2.2、觀察LiveData對(duì)象
通過(guò)observe方法來(lái)監(jiān)聽(tīng)LiveData的數(shù)據(jù)變化,每當(dāng)LiveData發(fā)生變化時(shí),都會(huì)回調(diào)onChanged方法,并返回值的內(nèi)容String s
liveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i(TAG, "onChanged: " + s);
}
});
2.3、更新LiveData對(duì)象
通過(guò)LiveData的setValue方法,給LiveData賦值,每次賦完值后,都會(huì)回調(diào)onChanged方法
liveData.setValue("add for test");
當(dāng)給LiveData賦值為"add for test"時(shí),onChanged會(huì)輸出日志:
2021-03-20 21:59:21.483 26430-26430/com.example.livedatademo I/LiveDataDemo: onChanged: add for test
3、編寫(xiě)LiveData Demo
我們創(chuàng)建一個(gè)Demo,主界面只有一個(gè)TextView,TextView用作展示一個(gè)數(shù)字,這個(gè)數(shù)字會(huì)從59開(kāi)始顯示,然后每隔1秒數(shù)字會(huì)減1,直到數(shù)字變?yōu)?。

接下來(lái),我們看下不使用LiveData和使用LiveData來(lái)實(shí)現(xiàn)這個(gè)Demo的區(qū)別
3.1、不使用LiveData
代碼說(shuō)明如下:
1、在MainActivity增加一個(gè)countDown的方法,通過(guò)CountDownTimer創(chuàng)建一個(gè)倒計(jì)時(shí)器
2、new CountDownTimer(1 * 60 * 1000, 1 * 1000)中2個(gè)參數(shù)的含義:第一個(gè)參數(shù)表示這個(gè)Timer的總時(shí)長(zhǎng)為60秒;第2個(gè)參數(shù)表示每隔1秒中會(huì)更新一次,并回調(diào)onTick方法
3、每次調(diào)用onTick方法,會(huì)調(diào)用textView.setText(String.valueOf(l / 1000));設(shè)置一次TextView的內(nèi)容對(duì)應(yīng)代碼如下:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "LiveDataDemo";
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
countDown();
}
private void countDown() {
new CountDownTimer(1 * 60 * 1000, 1 * 1000) {
@Override
public void onTick(long l) {
Log.i(TAG, "onTick: " + l);
textView.setText(String.valueOf(l / 1000));
}
@Override
public void onFinish() {
}
}.start();
}
}
- 弊端:
業(yè)務(wù)邏輯(倒計(jì)時(shí)的功能)和UI邏輯(TextView更新)沒(méi)有分開(kāi),耦合到一起了
3.2、使用MutableLiveData
為了方便演示,我們直接在MainActivity中操作LiveData,實(shí)際項(xiàng)目中不要這樣編寫(xiě)代碼,應(yīng)該把LiveData放到ViewModel中

代碼說(shuō)明如下:
1、在MainActivity中增加一個(gè)long類(lèi)型的MutableLiveData
2、每次回調(diào)onTick方法時(shí),調(diào)用liveData.setValue(l);,把最新的值設(shè)置給LiveData
3、調(diào)用LivewData的observe方法,設(shè)置一個(gè)監(jiān)聽(tīng)器,每當(dāng)LiveData的值變化時(shí),會(huì)回調(diào)onChanged方法,在onChanged中設(shè)置TextView的內(nèi)容對(duì)應(yīng)代碼如下:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "LiveDataDemo";
private final MutableLiveData<Long> liveData = new MutableLiveData<>();
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
// TODO:為了方便演示,我們直接在MainActivity中操作LiveData,實(shí)際項(xiàng)目中不要這樣編寫(xiě)代碼,應(yīng)該把LiveData放到ViewModel中
liveData.observe(this, new Observer<Long>() {
@Override
public void onChanged(Long aLong) {
textView.setText(String.valueOf(aLong / 1000));
}
});
countDown();
}
public void countDown() {
new CountDownTimer(1 * 60 * 1000, 1 * 1000) {
@Override
public void onTick(long l) {
Log.i(TAG, "onTick: " + l);
// TODO:為了方便演示,我們直接在MainActivity中操作LiveData,實(shí)際項(xiàng)目中不要這樣編寫(xiě)代碼,應(yīng)該把LiveData放到ViewModel中
liveData.setValue(l);
}
@Override
public void onFinish() {
}
}.start();
}
}
3.3、使用MediatorLiveData
MediatorLiveData可以合并多個(gè)LiveData源,只要任何原始的LiveData源對(duì)象發(fā)生更改,就會(huì)觸發(fā)MediatorLiveData對(duì)象的觀察者。
例如,如果界面中有可以從本地?cái)?shù)據(jù)庫(kù)或網(wǎng)絡(luò)更新的 LiveData 對(duì)象,則可以向MediatorLiveData 對(duì)象添加以下源:
- 與存儲(chǔ)在數(shù)據(jù)庫(kù)中的數(shù)據(jù)關(guān)聯(lián)的
LiveData對(duì)象。 - 與從網(wǎng)絡(luò)訪問(wèn)的數(shù)據(jù)關(guān)聯(lián)的
LiveData對(duì)象。
Activity只需觀察MediatorLiveData對(duì)象即可從這兩個(gè)源接收更新。接下來(lái),我們會(huì)實(shí)現(xiàn)這個(gè)例子。
3.3.1、監(jiān)聽(tīng)2個(gè)數(shù)據(jù)源的變化
-
代碼說(shuō)明如下:
1、創(chuàng)建1個(gè)MediatorLiveData<String>對(duì)象final MediatorLiveData<String> liveDataMerger = new MediatorLiveData<>();2、創(chuàng)建2個(gè)
MutableLiveData:liveData1表示網(wǎng)絡(luò)數(shù)據(jù)源,liveData2表示本地?cái)?shù)據(jù)源private MutableLiveData<String> liveData1 = new MutableLiveData<>(); private MutableLiveData<String> liveData2 = new MutableLiveData<>();3、調(diào)用
MediatorLiveData的addSource方法,分別將liveData1和liveData2加到MediatorLiveData要監(jiān)聽(tīng)的數(shù)據(jù)源中liveDataMerger.addSource(liveData1, new Observer<String>() { @Override public void onChanged(String s) { Log.i(TAG, "addSource1 onChanged: " + s); liveDataMerger.setValue(s); } }); liveDataMerger.addSource(liveData2, new Observer<String>() { @Override public void onChanged(String s) { Log.i(TAG, "addSource2 onChanged: " + s); liveDataMerger.setValue(s); } });4、設(shè)置
MediatorLiveData的監(jiān)聽(tīng),當(dāng)2個(gè)數(shù)據(jù)源發(fā)生變化時(shí),會(huì)回調(diào)onChanged方法,并將變化的內(nèi)容展示到TextView上liveDataMerger.observe(this, new Observer<String>() { @Override public void onChanged(String s) { Log.i(TAG, "liveDataMerger onChanged: " + s); textView.setText(s); }});
3.3.2、 編寫(xiě)模擬2個(gè)數(shù)據(jù)源更新的代碼
編寫(xiě)一個(gè)mergeTes的方法,里面創(chuàng)建了2個(gè)Timer,用作模擬網(wǎng)絡(luò)數(shù)據(jù)更新和本地?cái)?shù)據(jù)更新的情況,每隔3秒會(huì)往網(wǎng)絡(luò)數(shù)據(jù)liveData1設(shè)置值、每隔10秒會(huì)往本地?cái)?shù)據(jù)liveData2設(shè)置值。對(duì)應(yīng)代碼如下:
public void mergeTest() {
new CountDownTimer(1 * 60 * 1000, 3 * 1000) {
@Override
public void onTick(long l) {
liveData1.setValue("網(wǎng)絡(luò)有數(shù)據(jù)更新了" + l/1000);
}
@Override
public void onFinish() {
}
}.start();
new CountDownTimer(1 * 60 * 1000, 10 * 1000) {
@Override
public void onTick(long l) {
liveData2.setValue("本地?cái)?shù)據(jù)庫(kù)更新了" + l/1000);
}
@Override
public void onFinish() {
}
}.start();
}
3.3.4、MediatorLiveData運(yùn)行效果
每隔3秒,TextView更新為如下內(nèi)容:

每隔10秒,TextView更新為如下內(nèi)容:

4、ViewModel使用
4.1 創(chuàng)建ViewModel類(lèi)
創(chuàng)建一個(gè)MyViewModel類(lèi),繼承自ViewModel
import androidx.lifecycle.ViewModel;
public class MyViewMode extends ViewModel {
}
4.2 在Activity中使用
public class MainActivity extends AppCompatActivity {
private MyViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewModel = new ViewModelProvider(this).get(MyViewModel.class);
}
}
如果遇到new ViewModelProvider(this)報(bào)錯(cuò),就在app/build.gradle中加入依賴implementation "androidx.lifecycle:lifecycle-viewmodel:2.3.0"

5、結(jié)合ViewModel,重構(gòu)LiveData Demo
5.1、在ViewModel中增加LiveData
在MyViewModel中增加3個(gè)MutableLiveData,分別對(duì)應(yīng)在MainActivity中使用到的。并編寫(xiě)這3個(gè)LiveData的get方法
public class MyViewModel extends ViewModel {
private MutableLiveData<Long> liveData = new MutableLiveData<>();
private MutableLiveData<String> liveData1 = new MutableLiveData<>();
private MutableLiveData<String> liveData2 = new MutableLiveData<>();
public MutableLiveData<Long> getLiveData() {
return liveData;
}
public MutableLiveData<String> getLiveData1() {
return liveData1;
}
public MutableLiveData<String> getLiveData2() {
return liveData2;
}
}
5.2、在ViewModel中添加操作數(shù)據(jù)的邏輯
countDown、mergeTest這2個(gè)方法在操作數(shù)據(jù),從MainActivity中把這2個(gè)方法copy到 MyViewModel中
public class MyViewModel extends ViewModel {
private static final String TAG = "MyViewMode";
... ...
public void countDown() {
new CountDownTimer(1 * 60 * 1000, 1 * 1000) {
@Override
public void onTick(long l) {
Log.i(TAG, "onTick: " + l);
liveData.postValue(l);
}
@Override
public void onFinish() {
}
}.start();
}
public void mergeTest() {
new CountDownTimer(1 * 60 * 1000, 3 * 1000) {
@Override
public void onTick(long l) {
liveData1.postValue("網(wǎng)絡(luò)有數(shù)據(jù)更新了" + l / 1000);
}
@Override
public void onFinish() {
}
}.start();
new CountDownTimer(1 * 60 * 1000, 10 * 1000) {
@Override
public void onTick(long l) {
liveData2.postValue("本地?cái)?shù)據(jù)庫(kù)更新了" + l / 1000);
}
@Override
public void onFinish() {
}
}.start();
}
}
5.3 修改MainActivity中和liveData有關(guān)的代碼
1、刪除countDown,改用viewModel.countDown();
viewModel = new ViewModelProvider(this).get(MyViewModel.class);
viewModel.countDown();
2、用viewModel.getLiveData().observe替換liveData.observe
viewModel.getLiveData().observe(this, new Observer<Long>() {
@Override
public void onChanged(Long aLong) {
textView.setText(String.valueOf(aLong/1000));
}
});
3、刪除liveData相關(guān)代碼
經(jīng)過(guò)上述修改后,liveData相關(guān)的重構(gòu)已完成,MainActivity代碼如下:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "LiveDataDemo";
private TextView textView;
private MutableLiveData<String> liveData1 = new MutableLiveData<>();
private MutableLiveData<String> liveData2 = new MutableLiveData<>();
private MyViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
viewModel = new ViewModelProvider(this).get(MyViewModel.class);
viewModel.countDown();
.... ...
}
5.4、修改MyViewModel
增加liveDataMerger字段,并編寫(xiě)getLiveDataMerger()方法,這個(gè)方法里面的內(nèi)容,是從MainActivity中copy過(guò)來(lái)的
public class MyViewModel extends ViewModel {
private static final String TAG = "MyViewMode";
.... ...
private MediatorLiveData<String> liveDataMerger;
public MediatorLiveData<String> getLiveDataMerger() {
if (liveDataMerger == null) {
liveDataMerger = new MediatorLiveData<>();
}
liveDataMerger.addSource(liveData1, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i(TAG, "addSource1 onChanged: " + s);
liveDataMerger.setValue(s);
}
});
liveDataMerger.addSource(liveData2, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i(TAG, "addSource2 onChanged: " + s);
liveDataMerger.setValue(s);
}
});
return liveDataMerger;
}
... ...
}
5.5、修改MainActivity中和MediatorLiveData有關(guān)的代碼
1、使用viewModel.getLiveDataMerger().observe替換liveDataMerger.observe
viewModel.getLiveDataMerger().observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i(TAG, "liveDataMerger onChanged: " + s);
textView.setText(s);
}
});
2、使用viewModel.mergeTest();替換mergeTest()
viewModel.mergeTest();
3、刪除掉liveDataMerger相關(guān)的代碼
5.6 重構(gòu)后MainActivity的代碼
public class MainActivity extends AppCompatActivity {
private static final String TAG = "LiveDataDemo";
private TextView textView;
private MyViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
viewModel = new ViewModelProvider(this).get(MyViewModel.class);
viewModel.getLiveData().observe(this, new Observer<Long>() {
@Override
public void onChanged(Long aLong) {
textView.setText(String.valueOf(aLong / 1000));
}
});
viewModel.getLiveDataMerger().observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i(TAG, "liveDataMerger onChanged: " + s);
textView.setText(s);
}
});
viewModel.mergeTest();
// viewModel.countDown();
}
}
5.7 重構(gòu)后MyViewModel的代碼
public class MyViewModel extends ViewModel {
private static final String TAG = "MyViewMode";
private MutableLiveData<Long> liveData = new MutableLiveData<>();
private MutableLiveData<String> liveData1 = new MutableLiveData<>();
private MutableLiveData<String> liveData2 = new MutableLiveData<>();
private MediatorLiveData<String> liveDataMerger;
public MediatorLiveData<String> getLiveDataMerger() {
if (liveDataMerger == null) {
liveDataMerger = new MediatorLiveData<>();
}
liveDataMerger.addSource(liveData1, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i(TAG, "addSource1 onChanged: " + s);
liveDataMerger.setValue(s);
}
});
liveDataMerger.addSource(liveData2, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i(TAG, "addSource2 onChanged: " + s);
liveDataMerger.setValue(s);
}
});
return liveDataMerger;
}
public MutableLiveData<Long> getLiveData() {
return liveData;
}
public MutableLiveData<String> getLiveData1() {
return liveData1;
}
public MutableLiveData<String> getLiveData2() {
return liveData2;
}
public void countDown() {
new CountDownTimer(1 * 60 * 1000, 1 * 1000) {
@Override
public void onTick(long l) {
Log.i(TAG, "onTick: " + l);
liveData.postValue(l);
}
@Override
public void onFinish() {
}
}.start();
}
public void mergeTest() {
new CountDownTimer(1 * 60 * 1000, 3 * 1000) {
@Override
public void onTick(long l) {
liveData1.postValue("網(wǎng)絡(luò)有數(shù)據(jù)更新了" + l / 1000);
}
@Override
public void onFinish() {
}
}.start();
new CountDownTimer(1 * 60 * 1000, 10 * 1000) {
@Override
public void onTick(long l) {
liveData2.postValue("本地?cái)?shù)據(jù)庫(kù)更新了" + l / 1000);
}
@Override
public void onFinish() {
}
}.start();
}
}