在Google I/O之间,Google推出了包含LiveData和ViewModel的组件架构,这有助于开发者们使用MVVM开发Android应用程序。
官方文档连接(需联外网)
使用场景分为以下三种:
1.Activity、Fragment 存活期间 的数据存储;
2.bind同一Activity 的多个Fragment间数据共享;
3.独立或与LiveData配合实现代码解耦;
首先我们说第一种场景:
我们都知道android配置更改会影响数据的存储。这些配置更改包括屏幕旋转,键盘更改,语言更改和启用多窗口窗口。Android OS管理活动,片段和其他UI控制器的生命周期。Android Framework决定何时控制器将重新创建或销毁某些用户操作。如果系统破坏并重新创建任何活动并且UI数据丢失。下面的效果:左边是使用了我们ViewModel,右边的没有:
1568110684860.gif
image.png
活动生命周期,当配置发生变化时,活动必须销毁并重新创建新配置。因此,在活动运行期间创建的值将会破坏。ViewModel很好的解决了这个问题,而且它能存储的数据量远远大于在我们以前使用的 activity 的onSaveInstanceState()机制保存和恢复数据,但缺点很明显,onSaveInstanceState只适合保存少量的可以被序列化、反序列化的数据,假如我们需要保存是一个比较多,复杂的数据,这种机制明显不合适。
ViewModel 生命周期图:
image.png
代码:
public class MainViewModel extends ViewModel {
private int itemA,itemB = 0;
public MutableLiveData<Integer> itemALive = new MutableLiveData();
public int getItemB() {
return itemB;
}
public int getItemA() {
return itemA;
}
public void changeItem(){
//模拟一下耗时操作,网络请求等 ..
new CountDownTimer(5000,1000){
@Override
public void onTick(long millisUntilFinished) {
itemA += 1;
itemALive.setValue(itemA);
}
@Override
public void onFinish() {
//getCurrentItemA();
}
}.start();
}
}
public class Main1Activity extends AppCompatActivity {
MainViewModel mainViewModel;
TextView tvA,tvB;
Button btA,btB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main1);
mainViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
tvA = (TextView) findViewById(R.id.tvA);
tvB = (TextView) findViewById(R.id.tvB);
tvA.setText(mainViewModel.getItemA()+"");
tvB.setText(mainViewModel.getItemB()+"");
mainViewModel.itemALive.observe(this,new Observer<Integer>(){
@Override
public void onChanged(@Nullable Integer integer) {
tvA.setText(integer+"");
}
});
btA = findViewById(R.id.btnA);
btB = findViewById(R.id.btnB);
btA.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mainViewModel.changeItem();
}
});
btB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tvB.setText(3+"");
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
android:orientation="horizontal"
tools:context=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#20B2AA">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:text="Scorce"
android:visibility="gone"
android:textColor="#ffffffff"
android:textSize="30dp" />
<TextView
android:id="@+id/tvA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="120dp"
android:text="0"
android:textColor="#ffffffff"
android:textSize="50dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="220dp"
android:text="PLay A"
android:visibility="gone"
android:textColor="#ffffffff"
android:textSize="30dp" />
<Button
android:id="@+id/btnA"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="320dp"
android:layout_marginBottom="30dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="A +1"
android:textSize="32dp"
android:textColor="@color/colorPrimary"
android:background="#ffffff" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#40E0D0">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:text="Scorce"
android:textColor="#ffffffff"
android:visibility="gone"
android:textSize="30dp" />
<TextView
android:id="@+id/tvB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="120dp"
android:text="0"
android:textColor="#ffffffff"
android:textSize="50dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="220dp"
android:text="PLay B"
android:textColor="#ffffffff"
android:visibility="gone"
android:textSize="30dp" />
<Button
android:id="@+id/btnB"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="320dp"
android:layout_marginBottom="30dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="B +1"
android:textSize="32dp"
android:textColor="@color/colorPrimary"
android:background="#ffffff" />
</RelativeLayout>
</LinearLayout>
第二中和第三种的使用场景结合liveData 下一节继续剖析.