Jetpack之ViewModel与LiveData
1.页面配置更改数据不丢失
当设备因配置更改(横竖屏旋转,软键盘模式,设备分辨率,权限开关)导致Activity/Fragment重建,ViewModel中的数据并不会因此而丢失(数据保存读取下面讲),配合LiveData可以在页面重建后立马能收到最新保存的数据用以重新渲染页面。
2.生命周期感应
在ViewModel中难免会做一些网络请求或数据的处理,可以复写onCleared()方法,终止清理一些操作,释放内存。该方法在宿主onDestroy时被调用。
3.数据共享
对于单Activity,多Fragment的页面,可以使用ViewModel实现页面之间的数据共享
def lifecycle_version = "2.2.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
ViewModel案例
1.首先我们创建一个自己的myViewModel来继承ViewModel
这里用来存储变量numer
import androidx.lifecycle.ViewModel;
public class MyViewModel extends ViewModel {
public int number =0;
}
2.实例化myviewmodle对象
需要注意我们需要手动导入ViewModelProviders依赖
//创建MyViewModel
myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
3.通过按钮的点击对myviewmodel里面的数值进行操作
public class MainActivity extends AppCompatActivity {
MyViewModel myViewModel;
TextView textView;
Button button1,button2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init_view();
//创建MyViewModel
myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
textView.setText(String.valueOf(myViewModel.number));
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
myViewModel.number++;
textView.setText(String.valueOf(myViewModel.number));
}
});
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
myViewModel.number+=2;
textView.setText(String.valueOf(myViewModel.number));
}
});
}
private void init_view() {
textView=findViewById(R.id.textView);
button1=findViewById(R.id.add);
button2=findViewById(R.id.button2);
}
}
本例使用ViewModel,不会使得在屏幕倒置的情况下数据丢失。
LiveData的概述官方解释
LiveData是一个能够被观察的并持有数据的类,与其他的常规的可观察者不同,它关心组件的生命周期,意味着它尊重Activity、Fragment和Service的生命周期,这能够确保仅仅更新处于Start和Resume(生命活动周期)中的组件中的观察者。
1.保证ui与数据同步。LiveData遵循观察者模式,LiveData会在组件生命周期发生变化时发出通知,您可以合并代码来更新这些观察者对象中的UI,因为对生命周期的管理,所以你可以放心的在观察者中更新ui。
2.没有内存泄漏。因为观察者是绑定LifeCycle的,随着LifeCycle的销毁,观察者会自动被清理掉。
3.活动停止不会导致崩溃。如果观察者所在组件的生命周期不活跃,比如activity处于堆栈中,这时观察者不会接收到数据。
4.不需要手动管理生命周期。ui组件仅观察相关的数据,不需要结束或开始观察。LiveData会自动的管理这些,因为当它观察的同时知道生命周期的变化。
5.始终最新的数据。一个activity从后台返回时会立刻接收最新的数据。
6.适当的配置更改。如果activity或者fragment因为配置改变而重建,例如屏幕旋转,它将立刻接收最新的数据。
7.共享资源。你能够继承一个LiveData对象使用单例模式包装成一个系统服务,使其能够在app中共享。这个LiveData对象一次连接到系统服务,所有的需要该资源的观察者都可以观察该对象。
前面我们看到仅仅使用ViewModel的时候,每当数据发生改变我们都要调用textView.setText(String.valueOf(myViewModel.number));
来重新赋值,那有没有方式可以省去这一步骤呢,那么LiveData就派上了用场
1.首先我们还是创建ViewModel,值得注意的是我们数据的类型发生了改变现在使用的是MutableLiveData<Integer> Number
,并在构造方法对number进行赋值。
public class LiveData extends ViewModel {
private MutableLiveData<Integer> Number;
public MutableLiveData<Integer> getNumber() {
if(Number == null){
Number = new MutableLiveData<>();
Number.setValue(0);
}
return Number;
}
//该函数用于对数据进行操作,比如+1,或者-1
public void addNumber(int n){
Number.setValue(Number.getValue()+n);
}
}
2.使用观察者模式,进行监听数据的改变,liveData.getNumber().observe(this, new Observer<Integer>() {
public class LiveDataActivity extends AppCompatActivity {
ImageView button1,button2;
TextView textView;
LiveData liveData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live_data);
init_view();
//获取ViewModel对象
liveData = ViewModelProviders.of(this).get(LiveData.class);
//添加观察者,监听数据的改变,并在数据改变的时候重新赋值
liveData.getNumber().observe(this, new Observer<Integer>() {
@Override
//当数据改变就呼救此函数
public void onChanged(Integer integer) {
//显示当前的数
textView.setText(String.valueOf(integer));
}
});
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//加1操作
liveData.addNumber(1);
}
});
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//减1操作
liveData.addNumber(-1);
}
});
}
private void init_view() {
textView=findViewById(R.id.textView2);
button1=findViewById(R.id.imageView);
button2=findViewById(R.id.imageView2);
}
}