Android JetPack学习总结(二)

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方法才不会被调用。

发表评论