在真正接觸並使用MVVM架構的時候,整我的都很差了。由於我的以爲,MVVM相對於MVC、MVP學習難度比較大,設計的知識點不是一點半點。因此想慢慢記錄下本身的成長。若有錯誤但願指正。java
從零開始搭建MVVM架構系列文章(持續更新):
Android從零開始搭建MVVM架構(1)————DataBinding
Android從零開始搭建MVVM架構(2)————ViewModel
Android從零開始搭建MVVM架構(3)————LiveData
Android從零開始搭建MVVM架構(4)————Room(從入門到進階)
Android從零開始搭建MVVM架構(5)————Lifecycles
Android從零開始搭建MVVM架構(6)————使用玩Android API帶你搭建MVVM框架(初級篇)
Android從零開始搭建MVVM架構(7) ———— 使用玩Android API帶你搭建MVVM框架(終極篇)android
仍是那張圖AAC(Android Architecture Components)git
這篇咱們講LiveData組件github
首先咱們把簡單介紹下LiveData極其做用和特色。後面用例子來證實。架構
簡介:LiveData 是一個有生命週期感知 & 可觀察的數據持有者類
做用: 持久化的觀察數據的更改與變化
特色:
一、感知對應Activity的生命週期,只有生命週期處於onStart與onResume時,LiveData處於活動狀態,纔會把更新的數據通知至對應的Activity
二、當生命週期處於onStop或者onPause時,不回調數據更新,直至生命週期爲onResume時,當即回調
三、當生命週期處於onDestory時,觀察者會自動刪除,防止內存溢出
四、共享資源。可使用單例模式擴展LiveData對象以包裝系統服務,以即可以在應用程序中共享它們,同時有遵照了以上生命週期框架
LiveData有2個方法通知數據改變:異步
由於要作區別,我這裏先用一個TextView作標題,看起來清晰些,xml以下(若是不理解DataBinding使用的建議,從前幾篇文章開始看)ide
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="onlyLive" type="String" />
</data>
<LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" >
<LinearLayout android:layout_marginTop="30dp" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="單獨使用LiveData設置數據:" />
<TextView android:id="@+id/txt_only_live" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{onlyLive}" />
</LinearLayout>
</LinearLayout>
</layout>
複製代碼
public class LiveDataActivity extends AppCompatActivity {
ActivityLivedataBinding binding;
private MutableLiveData<String> liveData = new MutableLiveData<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_livedata);
binding = DataBindingUtil.setContentView(this, R.layout.activity_livedata);
binding.setOnlyLive(liveData.getValue());
//數據改變監聽
liveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
binding.setOnlyLive(s);
LogUtils.i("觀察LiveData", "單獨使用LiveData ==> " + s);
}
});
}
@Override
protected void onStop() {
super.onStop();
liveData.postValue("單獨LiveData使用");
}
}
複製代碼
//一、第一個參數是LifeCycleOwner。這樣也是咱們另一個組件.
// 在DataBinding篇,也說了,在26版本之後的Support庫中,
// AppCompatActivity和SupportActivity中都實現了LifecycleOwner,內部已經對UI界面的生命週期作了處理了。
// 這裏咱們學習的是LiveData,先暫且把他忽略調
//二、
liveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
binding.setOnlyLive(s);
ToastUtils.showToast(s);
}
});
複製代碼
//針對他的生命週期感知,咱們在按home鍵,在離開視圖界面的時候給他設置數據以下。而後看效果
@Override
protected void onStop() {
super.onStop();
liveData.postValue("單獨LiveData使用");
}
複製代碼
效果圖以下(按home鍵,程序進入後臺後再切進去):post
看到LiveData還須要經過監聽給xml設置數據。這個時候咱們會不禁的想起DataBinding的數據綁定,豈不是比他方便。那麼我加上DataBinding的雙向數據綁定看看。建一個測試類,用到咱們的ObservableField(不清楚的去看前幾篇)學習
public class TestBean {
public final ObservableField<String> name = new ObservableField<>();
private void setName(String name) {
this.name.set(name);
}
}
複製代碼
xml以下:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="onlyLive" type="String" />
<variable name="dataBsource" type="com.lihang.viewmodelstu.bean.TestBean" />
</data>
<LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" >
<LinearLayout android:layout_marginTop="30dp" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="單獨使用LiveData設置數據:" />
<TextView android:id="@+id/txt_only_live" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{onlyLive}" />
</LinearLayout>
<LinearLayout android:layout_marginTop="30dp" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="DataBinding雙向數據綁定設置數據:" />
<TextView android:id="@+id/txt_dataBinding" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@={dataBsource.name}" />
</LinearLayout>
</LinearLayout>
</layout>
複製代碼
Activity裏,由於DataBinding的數據綁定沒有觀察監聽,那咱們就對設置數據的textView作個監聽。
public class LiveDataActivity extends AppCompatActivity {
ActivityLivedataBinding binding;
private MutableLiveData<String> liveData = new MutableLiveData<>();
private TestBean testBean = new TestBean();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_livedata);
binding = DataBindingUtil.setContentView(this, R.layout.activity_livedata);
binding.setOnlyLive(liveData.getValue());
binding.setDataBsource(testBean);
addTextViewChange();
}
private void addTextViewChange() {
binding.txtOnlyLive.addTextChangedListener(new TextWatcher() {
....//省略部分代碼
@Override
public void afterTextChanged(Editable s) {
LogUtils.i("TextView的變化", "單獨使用LiveData ==> " + s);
}
});
binding.txtDataBinding.addTextChangedListener(new TextWatcher() {
....//省略部分代碼
@Override
public void afterTextChanged(Editable s) {
LogUtils.i("TextView的變化", "DataBinding雙向綁定 ==> " + s);
}
});
}
@Override
protected void onStop() {
super.onStop();
liveData.postValue("單獨LiveData使用");
testBean.name.set("我是DataBinding雙向綁定");
}
}
複製代碼
一樣在離開界面的時候設置下數據:
效果圖以下(咱們看打印):
上篇提到了LifecycleOwner。即便LiveData配合ViewModel使用,也要經過它來省去每次數據改變的監聽
怎麼用呢?
關鍵就是給咱們的DataBingding設置LifecycleOwner:binding.setLifecycleOwner(this);
來看咱們的ViewModel
public class LiveDataViewModel extends ViewModel {
private MutableLiveData<String> nameLiveData = new MutableLiveData<>();
public MutableLiveData<String> getData() {
return nameLiveData;
}
}
複製代碼
xml裏再加上一條顯示ViewModel的數據
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="onlyLive" type="String" />
<variable name="dataBsource" type="com.lihang.viewmodelstu.bean.TestBean" />
<variable name="liveViewModel" type="com.lihang.viewmodelstu.viewmodel.LiveDataViewModel" />
</data>
<LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" >
<LinearLayout android:layout_marginTop="30dp" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="單獨使用LiveData設置數據:" />
<TextView android:id="@+id/txt_only_live" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{onlyLive}" />
</LinearLayout>
<LinearLayout android:layout_marginTop="30dp" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="DataBinding雙向數據綁定設置數據:" />
<TextView android:id="@+id/txt_dataBinding" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@={dataBsource.name}" />
</LinearLayout>
<LinearLayout android:layout_marginTop="30dp" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="ViewModel配合LiveData設置數據:" />
<TextView android:id="@+id/txt_viewmodel_livedata" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{liveViewModel.data}" />
</LinearLayout>
</LinearLayout>
</layout>
複製代碼
Activity裏:
public class LiveDataActivity extends AppCompatActivity {
ActivityLivedataBinding binding;
private MutableLiveData<String> liveData = new MutableLiveData<>();
private TestBean testBean = new TestBean();
private LiveDataViewModel model;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_livedata);
binding = DataBindingUtil.setContentView(this, R.layout.activity_livedata);
binding.setOnlyLive(liveData.getValue());
binding.setDataBsource(testBean);
//本節重點是下面2句代碼哦
binding.setLifecycleOwner(this);
model = ViewModelProviders.of(this).get(LiveDataViewModel.class);
binding.setLiveViewModel(model);
addLiveObserve();
addTextViewChange();
}
private void addTextViewChange() {
binding.txtOnlyLive.addTextChangedListener(new TextWatcher() {
...//省略
@Override
public void afterTextChanged(Editable s) {
LogUtils.i("TextView的變化", "單獨使用LiveData ==> " + s);
}
});
binding.txtDataBinding.addTextChangedListener(new TextWatcher() {
...//省略
@Override
public void afterTextChanged(Editable s) {
LogUtils.i("TextView的變化", "DataBinding雙向綁定 ==> " + s);
}
});
binding.txtViewmodelLivedata.addTextChangedListener(new TextWatcher() {
...//省略
@Override
public void afterTextChanged(Editable s) {
LogUtils.i("TextView的變化", "ViewModel配合LiveData使用 ==> " + s);
}
});
}
private void addLiveObserve() {
liveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
//單獨使用的仍是須要監聽哦!
binding.setOnlyLive(s);
}
});
}
@Override
protected void onStop() {
super.onStop();
liveData.postValue("單獨LiveData使用");
testBean.name.set("我是DataBinding雙向綁定");
model.getData().postValue("ViewModel配合LiveData使用");
}
}
複製代碼
咱們經過model.getData().postValue("ViewModel配合LiveData使用");去改變ViewModel裏的數據,看結果: