Jetpack之ViewModel与LiveData

本章需要实现的效果图

在这里插入图片描述

ViewModel的优势

1.页面配置更改数据不丢失
当设备因配置更改(横竖屏旋转,软键盘模式,设备分辨率,权限开关)导致Activity/Fragment重建,ViewModel中的数据并不会因此而丢失(数据保存读取下面讲),配合LiveData可以在页面重建后立马能收到最新保存的数据用以重新渲染页面。

2.生命周期感应
在ViewModel中难免会做一些网络请求或数据的处理,可以复写onCleared()方法,终止清理一些操作,释放内存。该方法在宿主onDestroy时被调用。

3.数据共享
对于单Activity,多Fragment的页面,可以使用ViewModel实现页面之间的数据共享

导入jetpack中的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(生命活动周期)中的组件中的观察者。

使用LiveData的优势:

1.保证ui与数据同步。LiveData遵循观察者模式,LiveData会在组件生命周期发生变化时发出通知,您可以合并代码来更新这些观察者对象中的UI,因为对生命周期的管理,所以你可以放心的在观察者中更新ui。
2.没有内存泄漏。因为观察者是绑定LifeCycle的,随着LifeCycle的销毁,观察者会自动被清理掉。
3.活动停止不会导致崩溃。如果观察者所在组件的生命周期不活跃,比如activity处于堆栈中,这时观察者不会接收到数据。
4.不需要手动管理生命周期。ui组件仅观察相关的数据,不需要结束或开始观察。LiveData会自动的管理这些,因为当它观察的同时知道生命周期的变化。
5.始终最新的数据。一个activity从后台返回时会立刻接收最新的数据。
6.适当的配置更改。如果activity或者fragment因为配置改变而重建,例如屏幕旋转,它将立刻接收最新的数据。
7.共享资源。你能够继承一个LiveData对象使用单例模式包装成一个系统服务,使其能够在app中共享。这个LiveData对象一次连接到系统服务,所有的需要该资源的观察者都可以观察该对象。

为什么使用LiveData

前面我们看到仅仅使用ViewModel的时候,每当数据发生改变我们都要调用textView.setText(String.valueOf(myViewModel.number));来重新赋值,那有没有方式可以省去这一步骤呢,那么LiveData就派上了用场

1.首先我们还是创建ViewModel,值得注意的是我们数据的类型发生了改变现在使用的是MutableLiveData<Integer> Number,并在构造方法对number进行赋值。

LiveData案例


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);

    }
}

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页