文章目录

  • 组件(MVVM)
  • ViewModel
  • LiveData
  • DataBinding
  • 小案例(篮球积分器)
  • ViewModelSavedState
  • SharedPreferences
  • 简单使用
  • 自定义文件名
  • 类结构
  • 定义Model
  • AndroidViewModel和小案例


组件(MVVM)

Android livedata 的移除 android viewmodel livedata_安卓

当我们不适用ViewModel时,是直接对view进行操作,并且数据是直接存储在controller中

Android livedata 的移除 android viewmodel livedata_数据_02

ViewModel

ViewModel 将视图的数据和逻辑从具有生命周期特性的实体(如 Activity 和 Fragment)中剥离开来。直到关联的 Activity 或 Fragment 完全销毁时,ViewModel 才会随之消失,也就是说,即使在旋转屏幕导致 Fragment 被重新创建等事件中,视图数据依旧会被保留。ViewModels 不仅消除了常见的生命周期问题,而且可以帮助构建更为模块化、更方便测试的用户界面。

ViewModel的优点也很明显,为Activity 、Fragment存储数据,直到完全销毁。尤其是屏幕旋转的场景,常用的方法都是通过onSaveInstanceState()保存数据,再在onCreate()中恢复,真的是很麻烦。

其次因为ViewModel存储了数据,所以ViewModel可以在当前ActivityFragment中实现数据共享。

Android livedata 的移除 android viewmodel livedata_ide_03

  1. ViewModel
public class MyViewModel extends ViewModel {

    private  int number;

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }
}
  1. MainActivity
public class MainActivity extends AppCompatActivity {

    private MyViewModel myViewModel;
    private TextView textView;
    private Button button1,button2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        this.myViewModel = new ViewModelProvider(this).get(MyViewModel.class);

        this.textView = findViewById(R.id.textView);
        this.button1 = findViewById(R.id.button1);
        this.button2 = findViewById(R.id.button2);

        this.textView.setText(String.valueOf(this.myViewModel.getNumber()));

        this.button1.setOnClickListener(v -> {
            this.myViewModel.setNumber(this.myViewModel.getNumber()+1);
            this.textView.setText(String.valueOf(this.myViewModel.getNumber()));
        });

        this.button2.setOnClickListener(v -> {
            this.myViewModel.setNumber(this.myViewModel.getNumber()+2);
            this.textView.setText(String.valueOf(this.myViewModel.getNumber()));
        });
    }
}

注意:这里 **this.myViewModel = new ViewModelProvider(this).get(MyViewModel.class);**可能会报错,这是因为依赖版本不对的原因

解决方法:在build.grade中添加一条依赖

dependencies { implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' }

  1. 效果

此时就算旋转ViewText中的数值也不会改变了。


LiveData

LiveData 是一个可以感知 Activity 、Fragment生命周期的数据容器。当 LiveData 所持有的数据改变时,它会通知相应的界面代码进行更新。同时,LiveData 持有界面代码 Lifecycle 的引用,这意味着它会在界面代码(LifecycleOwner)的生命周期处于 started 或 resumed 时作出相应更新,而在 LifecycleOwner 被销毁时停止更新。

主要作用在两点:

  • 数据存储器类。也就是一个用来存储数据的类。
  • 可观察。这个数据存储类是可以观察的,也就是比一般的数据存储类多了这么一个功能,对于数据的变动能进行响应。

主要思想就是用到了观察者模式思想,让观察者和被观察者解耦,同时还能感知到数据的变化(其实就是通过setValue()进行感知),所以一般被用到ViewModel中,ViewModel负责触发数据的更新,更新会通知到LiveData,然后LiveData再通知活跃状态的观察者

Android livedata 的移除 android viewmodel livedata_android_04

  1. ViewModelLiveData
public class ViewModelLiveData extends ViewModel {

    private MutableLiveData<Integer> likeNumber;

    public MutableLiveData<Integer> getLikeNumber() {
        if(likeNumber == null) {
            likeNumber = new MutableLiveData<>();
            likeNumber.setValue(0);
        }
        return likeNumber;
    }

    public void addLikeNumber(Integer number){
        likeNumber.setValue(likeNumber.getValue() + number);
    }
}
  1. MainActivity
public class MainActivity extends AppCompatActivity {

    TextView textView;
    ImageButton imageButton1;
    ImageButton imageButton2;
    ViewModelLiveData viewModelLiveData;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.textView);
        imageButton1 = findViewById(R.id.imageButton1);
        imageButton2 = findViewById(R.id.imageButton2);

        viewModelLiveData = new ViewModelProvider(this).get(ViewModelLiveData.class);

        //相当于一个观察者,当数据发生改变时,会自动的对textView进行一次刷新
        //其他地方就不会出现对textView的修改了,进一步增加了代码的独立性77
        viewModelLiveData.getLikeNumber().observe(this,integer -> {
            textView.setText(String.valueOf(integer));
        });

        //+1
        imageButton1.setOnClickListener(view->{
            viewModelLiveData.addLikeNumber(1);
        });

        //-1
        imageButton2.setOnClickListener(view->{
            viewModelLiveData.addLikeNumber(-1);
        });
    }
}
  1. 效果


DataBinding

什么是 DataBinding 呢,简单说来就是帮我们实现 view 和 data 绑定的工具,把数据映射到 view 的 xml中,可以在 xml 布局文件中实现 view 的赋值,方法调用。使用 DataBinding 后,我们不同再写 findViewById,不用再获取控件对象,不用再设置监听,可以节省我们 activity 中的很多获取控件,赋值,添加监听所需要的代码。

DataBinding 是个好东西,15年 google IO 大会就开始推了,最直接的变化就是催生了 android 中 MVVM 的出现,MVVM = MVP + DataBinding 。

DataBinding可以帮我们减少很多没必要的代码,大大提高我们的开发效率。比如大量减少使用findViewById()、setText(),setVisibility(),setEnabled()等代码的几率。

DataBinding主要解决了两个问题:

  • 需要多次使用findViewById等无营养的代码,损害了应用性能且令人厌烦
  • 更新UI数据需切换至UI线程,将数据分解映射到各个view比较麻烦

Android livedata 的移除 android viewmodel livedata_ide_05

  1. 修改配置
android {
    compileSdkVersion 30
    buildToolsVersion "30.0.2"

    defaultConfig {
        dataBinding {
            enabled true
        }
    }
}

上面写法已经过时,写下面这种写法

android {
    buildFeatures {
        dataBinding = true
    }
}
  1. 转换为databing形式的layout

然后会自动帮我们创建一个ActivityMainBinding

  1. 创建ViewModel
public class MyViewModel extends ViewModel {

    private MutableLiveData<Integer> likeNumber;

    public MutableLiveData<Integer> getLikeNumber() {
        if(likeNumber == null) {
            likeNumber = new MutableLiveData<>();
            likeNumber.setValue(0);
        }
        return likeNumber;
    }

    public void add(){
        likeNumber.setValue(likeNumber.getValue() + 1);
    }
}
  1. MainActivity(进行一个绑定)
public class MainActivity extends AppCompatActivity {

    MyViewModel myViewModel;
    ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main);

        myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
        binding.setData(myViewModel);
        binding.setLifecycleOwner(this);
    }
}
  1. 在view中设置好变量,并进行属性和函数调用,我们调用属性其实本质上调用的是get()方法。
<data>
    <variable
          name="data"
          type="com.example.databinding.MyViewModel" />
</data>

<TextView
          android:id="@+id/textView"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@{String.valueOf(data.likeNumber)}"
          android:textSize="36sp"
          app:layout_constraintBottom_toBottomOf="parent"
          app:layout_constraintLeft_toLeftOf="parent"
          app:layout_constraintRight_toRightOf="parent"
          app:layout_constraintTop_toTopOf="parent"
          app:layout_constraintVertical_bias="0.251" />

<Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="384dp"
        android:text="@string/button"
        android:onClick="@{()->data.add()}"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


小案例(篮球积分器)

  1. 创建一个项目,并修改配置
plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.2"

    defaultConfig {
        applicationId "com.example.score"
        minSdkVersion 30
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildFeatures {
        dataBinding = true
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
}
  1. 创建视图
  2. 创建ViewModel
public class MyViewModel extends ViewModel {

    private MutableLiveData<Integer> aTeamScore;
    private MutableLiveData<Integer> bTeamScore;
    /**
    /* 存储回退数值
    */
    private Integer aBack,bBack;

    public MutableLiveData<Integer> getATeamScore() {
        if(aTeamScore == null){
            aTeamScore = new MutableLiveData<>();
            aTeamScore.setValue(0);
        }
        return aTeamScore;
    }

    public MutableLiveData<Integer> getBTeamScore() {
        if(bTeamScore == null){
            bTeamScore = new MutableLiveData<>();
            bTeamScore.setValue(0);
        }
        return bTeamScore;
    }

    public void aTeamAdd(int p){
        aBack = aTeamScore.getValue();
        bBack = bTeamScore.getValue();
        aTeamScore.setValue(aTeamScore.getValue()+p);
    }

    public void bTeamAdd(int p){
        aBack = aTeamScore.getValue();
        bBack = bTeamScore.getValue();
        bTeamScore.setValue(bTeamScore.getValue()+p);
    }

    /**
    * @Description 重置
    * @date 2020/11/12 11:10
    * @return
    */
    public void reset(){
        aTeamScore.setValue(0);
        bTeamScore.setValue(0);
    }

    /**
    * @Description 撤销操作
    * @date 2020/11/12 11:09
    * @return
    */
    public void undo(){
        aTeamScore.setValue(aBack);
        bTeamScore.setValue(bBack);
    }
}
  1. 使用DataBinding,并调用ViewModel中的属性和方法
  2. MainActivity
public class MainActivity extends AppCompatActivity {

    MyViewModel myViewModel;
    ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        myViewModel = new ViewModelProvider(this).get(MyViewModel.class);

        binding.setData(myViewModel);
        binding.setLifecycleOwner(this);
    }
}
  1. 之后创建一个横版的,并修改样式
  2. 演示


ViewModelSavedState

在上面的例子中,我们的数据存在ViewModel中,理论上是不会被清除的,相比于onSaveInstanceState确实方便了不少,但如果我们的进程被后台系统杀死,数据就会丢失

Android livedata 的移除 android viewmodel livedata_数据_06

我们这里来检验一下(因为之前的本地化多语言,我将虚拟机切换成立了中文)。

  1. 打开开发者模式:设置->关于模拟设备->版本号(连续点击进入开发者模式)
  2. 设置不保留活动:**设置->系统->开发者选项->下滑到 ‘应用’ 栏->打开 ‘不保留活动’ 选项 或者 选择后台进程限制的不允许后台进程 **
  3. 进行测试

解决办法

  • onSaveInstanceState(太旧了)
  • viewModelSavedState

onSaveInstanceState方法

public class MainActivity extends AppCompatActivity {

    MyViewModel myViewModel;
    ActivityMainBinding binding;
    private static  final String KEY_A_NUMBER = "A_number";
    private static  final String KEY_B_NUMBER = "B_number";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        myViewModel = new ViewModelProvider(this).get(MyViewModel.class);

        if(savedInstanceState!=null){
            myViewModel.getATeamScore().setValue((Integer) savedInstanceState.get(KEY_A_NUMBER));
            myViewModel.getBTeamScore().setValue((Integer) savedInstanceState.get(KEY_B_NUMBER));
        }

        binding.setData(myViewModel);
        binding.setLifecycleOwner(this);

    }

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(KEY_A_NUMBER, myViewModel.getATeamScore().getValue());
        outState.putInt(KEY_B_NUMBER, myViewModel.getBTeamScore().getValue());
    }
}

viewModelSavedState方法

Android livedata 的移除 android viewmodel livedata_数据_07

  1. 添加依赖
implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0'
  1. 修改ViewModel
public class MyViewModel extends ViewModel {

    //private MutableLiveData<Integer> aTeamScore;
    //private MutableLiveData<Integer> bTeamScore;
    private Integer aBack,bBack;

    private SavedStateHandle handle;

    private static  final String KEY_A_NUMBER = "A_number";
    private static  final String KEY_B_NUMBER = "B_number";

    public MyViewModel(SavedStateHandle handle) {
        this.handle = handle;
    }

    public MutableLiveData<Integer> getATeamScore() {
        if(!handle.contains(KEY_A_NUMBER)){
            handle.set(KEY_A_NUMBER,0);
        }
        return handle.getLiveData(KEY_A_NUMBER);
    }

    public MutableLiveData<Integer> getBTeamScore() {
        if(!handle.contains(KEY_B_NUMBER)){
            handle.set(KEY_B_NUMBER,0);
        }
        return handle.getLiveData(KEY_B_NUMBER);
    }

    public void aTeamAdd(int p){
        aBack = (Integer) handle.getLiveData(KEY_A_NUMBER).getValue();
        bBack = (Integer) handle.getLiveData(KEY_B_NUMBER).getValue();
        handle.set(KEY_A_NUMBER,aBack+p);
    }

    public void bTeamAdd(int p){
        aBack = (Integer) handle.getLiveData(KEY_A_NUMBER).getValue();
        bBack = (Integer) handle.getLiveData(KEY_B_NUMBER).getValue();
        handle.set(KEY_B_NUMBER,bBack+p);
    }

    /**
    * @Description 重置
    * @date 2020/11/12 11:10
    * @return
    */
    public void reset(){
        handle.set(KEY_A_NUMBER,0);
        handle.set(KEY_B_NUMBER,0);
    }

    /**
    * @Description 撤销操作
    * @date 2020/11/12 11:09
    * @return
    */
    public void undo(){
        handle.set(KEY_A_NUMBER,aBack);
        handle.set(KEY_B_NUMBER,bBack);
    }
}
  1. 修改MainActivity
public class MainActivity extends AppCompatActivity {

    MyViewModel myViewModel;
    ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        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);

    }
}


SharedPreferences

通过上面的ViewModelSavedState,我们进入后台后数据也不会丢失了,但是当我们点击返回时,数据还会丢失。

Android livedata 的移除 android viewmodel livedata_android_08

解决办法:SharedPreferences,永久保存数据

Android livedata 的移除 android viewmodel livedata_数据_09

简单使用
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        SharedPreferences shp = getPreferences(Context.MODE_PRIVATE);
        
        //存储数据
        SharedPreferences.Editor edit = shp.edit();
        edit.putInt("NUMBER", 100);
        edit.commit();
        
        //读取
        int x = shp.getInt("NUMBER", 0);
        Log.d("myLog", "onCreate:"+x);
    }
}

运行代码,控制台日志打印如下

Android livedata 的移除 android viewmodel livedata_android_10

然后找到右下角的

Android livedata 的移除 android viewmodel livedata_android_11

点击,会看到一个目录,进入到data/data/,你会看到很多的包名,然后找到你当前MainActivity所在的包名,单击右键,进行一次刷新

Android livedata 的移除 android viewmodel livedata_ide_12

其中的数据如下

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <int name="NUMBER" value="100" />
</map>



自定义文件名
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //SharedPreferences shp = getPreferences(Context.MODE_PRIVATE);
        SharedPreferences shp = getSharedPreferences("My_DATA", Context.MODE_PRIVATE);

        //存储数据
        SharedPreferences.Editor edit = shp.edit();
        edit.putInt("NUMBER", 600);
        edit.commit();

        //读取
        int x = shp.getInt("NUMBER", 0);
        Log.d("myLog", "onCreate:"+x);
    }
}

运行

Android livedata 的移除 android viewmodel livedata_android_13



类结构

Android livedata 的移除 android viewmodel livedata_数据_14

我们当前的类继承自ContextWrapper类,getSharedPreferences方法是在ContextWrapper类中定义的。

Android livedata 的移除 android viewmodel livedata_数据_15



定义Model
public class MyData {

    private int data;

    private Context context;
    private Resources resources;

    private SharedPreferences shp;

    /**
    * @Description 初始化基本信息,必须传入context对象
    * @date 2020/11/14 14:56
    * @param context
    * @return
    */
    public MyData(Context context) {
        this.context = context;
        this.resources = context.getResources();
        shp = context.getSharedPreferences(resources.getString(R.string.MY_DATA),Context.MODE_PRIVATE);
    }

    /**
    * @Description 存储数据
    * @date 2020/11/14 14:55
    * @return
    */
    public void save(){
        SharedPreferences.Editor edit = shp.edit();
        edit.putInt(resources.getString(R.string.MY_KEY), data);
        edit.commit();
    }

    /**
    * @Description 读取数据
    * @date 2020/11/14 14:55
    * @return
    */
    public int load(){
        data = shp.getInt(resources.getString(R.string.MY_KEY), resources.getInteger(R.integer.defValue));
        return data;
    }

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }
}

其中使用到的常量放在了资源中,自己创建一个int资源

-----string.xml-----
<resources>
    <string name="app_name">SharedPreferences</string>
    <string name="MY_DATA">my_data</string>
    <string name="MY_KEY">my_key</string>
</resources>

-----int.xml-----
<resources>
    <integer name="defValue">0</integer>
</resources>

在MainActivity中可以定义一个MyData,并传入context

MyData myData = new MyData(this);

这样子传可以,但不好,因为可能会引起内存的泄露。因为我们的Activity在翻转,切换等情况会进行重新创建,而我们的myData中又有一个引用指向Activity,就会导致当前Activity对象并不会被垃圾回收器回收。

应该传递Application,只要应用还存在,就不会被重新创建。

MyData myData = new MyData(getApplication());

Android livedata 的移除 android viewmodel livedata_安卓_16

MainActivity代码

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    MyData myData = new MyData(getApplication());
    myData.setData(800);
    myData.save();

    Log.d("myLog", "onCreate:"+myData.load());
}

之后自己可以查看结果



AndroidViewModel和小案例

首先,修改配置build.gradle,导入依赖

buildFeatures {
    dataBinding = true
}

implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0'

做个界面

Android livedata 的移除 android viewmodel livedata_android_17

编写viewModel

package com.example.viewmodelshp;

import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.SavedStateHandle;

/**
 * @author codekiller
 * @date 2020/11/14 15:19
 * @Description ViewModel
 */
public class MyViewModel extends AndroidViewModel {

    private SavedStateHandle handle;

    private String key = getApplication().getString(R.string.data_key);
    private String shpName = getApplication().getString(R.string.shp_name);

    public MyViewModel(@NonNull Application application, SavedStateHandle savedStateHandle) {
        super(application);
        this.handle = savedStateHandle;

        if (!this.handle.contains(key)) {
            load();
        }
    }

    public LiveData<Integer> getNumber() {
        return handle.getLiveData(key);
    }

    /**
     * @return
     * @Description 加载数据
     * @date 2020/11/14 15:41
     */
    public void load() {
        SharedPreferences shp = getApplication().getSharedPreferences(shpName, Context.MODE_PRIVATE);
        handle.set(key, shp.getInt(key, 0));
    }

    /**
     * @return
     * @Description 保存数据
     * @date 2020/11/14 15:41
     */
    public void save() {
        SharedPreferences shp = getApplication().getSharedPreferences(shpName, Context.MODE_PRIVATE);
        SharedPreferences.Editor edit = shp.edit();
        edit.putInt(key, getNumber().getValue());
        edit.commit();
    }

    /**
     * @param x
     * @return
     * @Description 进行+和-运算
     * @date 2020/11/14 15:39
     */
    public void add(int x) {
        handle.set(key, getNumber().getValue() + x);
        //save(); 耗时间
    }

}



常量资源

<resources>
    <string name="app_name">ViewModelSHP</string>
    <string name="button_plus">+</string>
    <string name="button_minus">-</string>
    <string name="textview">HelloWorld</string>
    <string name="data_key">DATA_KEY</string>
    <string name="shp_name">shp_name</string>
</resources>

修改activity_main.xml,先转化为data binding layout,再修改代码(这里给出了修改的部分)

<data>
    <variable
            name="data"
            type="com.example.viewmodelshp.MyViewModel" />
</data>

<TextView
	android:text="@{String.valueOf(data.getNumber())}"/>

<Button
        android:onClick="@{()->data.add(1)}"/>

<Button
        android:onClick="@{()->data.add(-1)}"/>

修改MainActivity

public class MainActivity extends AppCompatActivity {

    MyViewModel myViewModel;
    ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        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);
    }

    @Override
    protected void onPause() {
        super.onPause();
        //保存数据
        myViewModel.save();
    }
}

之后,不论是进程杀死,还是退出应用,关机,数据都不会丢失。但是如果你手机没电了突然关机,onPause()调用不了,数据依然会丢失。