前言
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則是完全是整個實體類或者數據類型變化后才通知.不會細節到某個字段
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,一直處於活動狀態,不管是否在前台哪里都會獲得回調。
END