前言
LiveData與ViewMode是經常搭配在一起使用的,但是為了不太混亂,我還是拆分開來說明,此篇博客只講解 LiveData 與 MutableLiveData的概念與使用方式(但是會涉及到ViewMode的部分代碼).
LiveData是干什么的?
由於LiveData和MutableLiveData都是一個概念的東西(只是作用范圍不同)所以就不重復解釋了,直接理解LiveData就可以明白MutableLiveData
直接理解LiveData的字面意思是前台數據,其實這其實是很准確的表達.下面我們來說說LiveData的幾個特征:
1.首先LiveData其實與數據實體類(POJO類)是一樣的東西,它負責暫存數據.
2.其次LiveData其實也是一個觀察者模式的數據實體類,它可以跟它注冊的觀察者回調數據是否已經更新.
3.LiveData還能知曉它綁定的Activity或者Fragment的生命周期,它只會給前台活動的activity回調(這個很厲害).這樣你可以放心的在它的回調方法里直接將數據添加到View,而不用擔心會不會報錯.(你也可以不用費心費力判斷Fragment是否還存活)
LiveData與MutableLiveData區別
LiveData與MutableLiveData的其實在概念上是一模一樣的.唯一幾個的區別如下:
1.MutableLiveData的父類是LiveData
2.LiveData在實體類里可以通知指定某個字段的數據更新.
3.MutableLiveData則是完全是整個實體類或者數據類型變化后才通知.不會細節到某個字段
4.LiveData不可變,MutableLiveData是可變的 -- 這個可能會讓人有點誤解,在博客最下面會解釋.
LiveData簡單使用Demo
創建LiveData
public class DemoData extends LiveData<DemoData> {
private int tag1;
private int tag2;
public int getTag1() {
return tag1;
}
public void setTag1(int tag1) {
this.tag1 = tag1;
postValue(this);
}
public int getTag2() {
return tag2;
}
public void setTag2(int tag2) {
this.tag2 = tag2;
postValue(this);
}
}
很簡單,只要繼承LiveData並且在泛型里寫下你的實體類,唯一需要注意的,postValue(this);這個方法是用於回調數據更新的方法. 你可以在你需要被觀察的數據里添加.
創建ViewModel
我們需要在ViewModel實例化DemoData這個類. ViewModel(這個會在另一篇博客介紹)這個是用於管理多個Activity或者Fragment數據的類。ViewModel是MVVM的概念。你可以百度一下,google提供這套東西就是為了MVVM。
public class DemoViewModel extends ViewModel {
// TODO: Implement the ViewModel
private DemoData mDemoData = new DemoData();
public DemoData getDemoData() {
return mDemoData;
}
}
在Activity或者Fragment綁定
public class Demo2Activity extends AppCompatActivity {
private static final String TAG = "Demo2Activity";
private Button mBtnAddData;
private DemoViewModel mDemoViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo2);
mBtnAddData = findViewById(R.id.btn_add_data);
mDemoViewModel = ViewModelProviders.of(this).get(DemoViewModel.class);//獲取ViewModel,讓ViewModel與此activity綁定
mDemoViewModel.getDemoData().observe(this, new Observer<DemoData>() { //注冊觀察者,觀察數據的變化
@Override
public void onChanged(DemoData demoData) {
Log.e(TAG, "onChanged: 數據有更新");
}
});
mBtnAddData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "onClick: 已經點擊");
mDemoViewModel.getDemoData().setTag1(123); //這里手動用按鍵點擊更新數據
}
});
}
}
當我們點擊按鍵后就會有數據更新后的回調觸發:
2019-09-18 19:45:53.821 6649-6649/demo.yt.com.demo E/Demo2Activity: onClick: 已經點擊 2019-09-18 19:45:53.824 6649-6649/demo.yt.com.demo E/Demo2Activity: onChanged: 數據有更新
前面提過了,但是這里還是需要重新提一下! 注意! 這個數據只給前台的活動回調.
MutableLiveData簡單使用Demo
前面已經解釋了,所以我們這邊直接看代碼
創建MutableLiveData
public class DemoViewModel extends ViewModel {
// TODO: Implement the ViewModel
private MutableLiveData<String> myString = new MutableLiveData<>();
public MutableLiveData<String> getMyString(){
return myString;
}
public void setMyString(String string) {
this.myString.setValue(string);
}
}
因為MutableLiveData只是作用於變量所以我們直接就可以在ViewModel里實例化它,並且在泛型里標注變量的類型.
public class MutableLiveData<T> extends LiveData<T> {
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
在Activity或者Fragment綁定
public class Demo1Activity extends AppCompatActivity {
private static final String TAG = "Demo1Activity";
private DemoViewModel mDemoViewModel;
private Button mBtn1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
mBtn1 = findViewById(R.id.btn_1);
mDemoViewModel = ViewModelProviders.of(this).get(DemoViewModel.class);//獲取ViewModel,讓ViewModel與此activity綁定
mDemoViewModel.getMyString().observe(this, new Observer<String>() { //注冊觀察者
@Override
public void onChanged(String s) {
Log.e(TAG, "onChanged: 值有變化="+s);
}
});
mBtn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDemoViewModel.setMyString("測試"); //用手動按鍵點擊改變值
}
});
}
}
結果:
2019-09-18 19:59:38.294 6961-6961/demo.yt.com.demo E/Demo1Activity: onChanged: 值有變化=測試
API全解
postValue()
可能你已經在上面看到幾次調用此方法了。postValue的特性如下:
1.此方法可以在其他線程中調用
2.如果在主線程執行發布的任務之前多次調用此方法,則僅將分配最后一個值。
3.如果同時調用 .postValue(“a”)和.setValue(“b”),一定是值b被值a覆蓋。
setValue()
setValue()的特性如下:
1.此方法只能在主線程里調用
getValue()
返回當前值。 注意,在后台線程上調用此方法並不能保證將接收到最新的值。
removeObserver(@NonNull final Observer<? super T> observer)
移除指定的觀察者
例子:
Observer<String> observer = new Observer<String>() {
@Override
public void onChanged(String s) {
mText.setText("內容改變=" + s);
}
};
mMainViewModel.getContent().observe(this, observer);//綁定
mMainViewModel.getContent().removeObserver(observer);//解除
removeObservers(@NonNull final LifecycleOwner owner)
移除當前Activity或者Fragment的全部觀察者
mMainViewModel.getContent().removeObservers(this);
hasActiveObservers()
如果此LiveData具有活動(Activity或者Fragment在前台,當前屏幕顯示)的觀察者,則返回true。其實如果這個數據的觀察者在最前台就返回true,否則false。
hasObservers()
如果此LiveData具有觀察者,則返回true。
observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)
設置此LiveData數據當前activity或者Fragment的觀察者,會給此activity或者Fragment在前台時回調數據。
observeForever(@NonNull Observer<? super T> observer)
1.設置永遠觀察者,永遠不會被自動刪除。您需要手動調用removeObserver(Observer)以停止觀察此LiveData,
2.設置后此LiveData,一直處於活動狀態,不管是否在前台哪里都會獲得回調。
MutableLiveData與LiveData區別:可變與不可變
初步學習后,很多人容易誤解所謂的LiveData可變與MutableLiveData不可變, 認為LiveData不是也可以set與post數據嘛? 怎么就不可變了
其實關鍵是LiveData是抽象類它的setValue與postValue 方法都是protected關鍵字, 而MutableLiveData是繼承LiveData后將setValue與postValue都public了. 這里的可變與不可變是對外部調用時的情況,LiveData對外隱藏了setValue與postValue.
這里又引申了一個android官方實現MutableLiveData模版代碼,讓MutableLiveData的setValue與postValue不暴露出去,代碼如下:
kotlin寫法:
val name: LiveData<NameBean> get() = _name
private val _name = MutableLiveData<NameBean>()
java寫法:
private MutableLiveData<NameBean> name = new MutableLiveData<>();
public LiveData<NameBean> getName(){
return name;
}
在外部調用時可以看到的情況,只有getValue()方法暴露


