ViewModelSavedState
ViewModelSavedState用于,当后台杀死某activity时存储和恢复数据。用onSavedInstanceState也可以实现,ViewModelSavedState是ViewModel自带的一个功能。
添加依赖
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0'
在ViewModel中可以创建新的构造方法
public class MyViewModel extends ViewModel {
private SavedStateHandle handle;
public MyViewModel(SavedStateHandle handle){//类似bundle
this.handle=handle;
}
//...
}
实际上使用SavedStateHandle之后就可以不必手动定义LiveData的数据了,一切数据都能从SavedStateHandle中取:
public class MyViewModel extends ViewModel {
private SavedStateHandle handle;
public MyViewModel(SavedStateHandle handle){//类似bundle
this.handle=handle;
}
public MutableLiveData<Integer> getNumber() {
if (!handle.contains(MainActivity.KEY_NUMBER)){
handle.set(MainActivity.KEY_NUMBER,0);
}
return handle.getLiveData(MainActivity.KEY_NUMBER);
}
public void add(){
getNumber().setValue(getNumber().getValue()+1);
}
}
在activity中使用新的构造方法
public class MainActivity extends AppCompatActivity {
ActivityMainBinding binding;
MyViewModel myViewModel;
public final static String KEY_NUMBER="my_number";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding= DataBindingUtil.setContentView(this,R.layout.activity_main);
myViewModel=new ViewModelProvider(this,new SavedStateViewModelFactory(getApplication(),this)).get(MyViewModel.class);
binding.setData(myViewModel);
binding.setLifecycleOwner(this);
}
}
AndroidViewModel
SharedPerferences需要设备上下文contex,在一个普通类中使用之需要我们手动传入context,但是这样可能会有内存泄漏的风险。
AndroidViewModel是ViewModel的一个子类,这个子类有对系统contex直接访问的一个工具,它要求继承该类的子类必须要创建一个含有application参数的构造方法,并且可以调用getApplication来获取context。
public class MyViewModel extends AndroidViewModel {
String key = getApplication().getResources().getString(R.string.data_key);
String shpName = getApplication().getResources().getString(R.string.shp_name);
SavedStateHandle handle;
public LiveData<Integer> getNumber() {
return handle.getLiveData(key);
}
public MyViewModel(@NonNull Application application, SavedStateHandle handle) {
super(application);
this.handle = handle;
if (!handle.contains(key)) {
load();
}
}
void load() {
SharedPreferences sharedPreferences = getApplication().getSharedPreferences(shpName, Context.MODE_PRIVATE);
int x = sharedPreferences.getInt(key, 0);
handle.set(key, x);
}
void save() {
SharedPreferences sharedPreferences = getApplication().getSharedPreferences(shpName, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt(key, getNumber().getValue());
editor.apply();
}
public void add(int x) {
handle.set(key, getNumber().getValue() + x);
}
}
save方法的调用时机
可以在add方法中调用,即每当用户点击按钮时就将结果保存到本地,但是这样效率不是很高。可以存放在activity的onPause()方法中,数据时相对很可靠的,且存储频率也不是很高,只有在死机、没电等activity毫无征兆地被摧毁时onPause方法才不会被调用。