ViewModel基本教程

转载请注明链接: https://blog.csdn.net/feather_wch/article/details/88667037

ViewModel基本教程

版本号:2019-03-22(11:30)


简介

1、ViewModel是什么?

  1. 用于存储和管理UI相关的数据
  2. 允许ViewModel在屏幕旋转等Configutation Changes的场景下依然保存数据

2、Activity在重建时是如何恢复数据的?

  1. onSaveInstanceState()中恢复从onCreate()中获取的Bundle
  2. 这种方法只适合恢复少量的可以序列化/反序列化的数据
  3. 如果是大量的数据如用户信息列表Bitmap就不适合该场景

3、onSaveInstanceState()恢复数据的缺点?

4、如果Activity获取的操作是耗时的异步操作,还需要避免内存泄露,此外每次重建都重新请求,非常浪费资源。

5、ViewModel存在的意义

  1. Activity、Fragment等UI控制器,如果去控制app所有的逻辑,包括数据的请求等,会导致非常难以维护
  2. ViewModel能将视图的数据相关的工作UI controller逻辑分离

ViewModel的使用

1、ViewModel的使用

  1. 将数据相关的逻辑都放置到ViewModel中,如存放一个用户信息列表
  2. ViewModel还需要处理加载用户信息列表的逻辑
public class MyViewModel extends ViewModel {
  // 1. 用户信息,列表
    private MutableLiveData<List<User>> users;
  // 2. 获取到用户信息列表
    public LiveData<List<User>> getUsers() {
        if (users == null) {
            users = new MutableLiveData<List<User>>();
            loadUsers();
        }
        return users;
    }
  // 3. 实际加载用户信息列表,可以从数据库或者网络中
    private void loadUsers() {
        // Do an asynchronous operation to fetch users.
    }
}

2、ViewModel的构建,以及注册监听用户信息列表的变化,数据发生改变后就自动更新UI

  1. 一定要在onCreate()中进行处理
public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        // 1. 第一次执行会创建ViewModel,Activity重建后调用到该方法会获取到之前的ViewModel
        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);

        // 2. 注册对LiveData的观察,将本Activity作为观察者
        model.getUsers().observe(this, users -> {
            // update UI
        });
    }
}

3、当Activity销毁时,framework会调用ViewModel的onCleared()方法对资源进行清理

特别要点

4、ViewModel绝对不要持有下列引用

  1. view
  2. Lifecycle
  3. 其他任何可能持有Activity Context的类的引用

5、ViewModel绝对不能去观察一个生命周期感知的被观察者,例如LiveData

AndroidViewModel

1、如果ViewModel需要Applicaiton的Context(为了获取系统服务),该如何处理?

  1. 自定义一个类,继承自AndroidViewModel
  2. 构造器一定要有一个唯一参数-Application'的对象

生命周期

1、ViewModel的生命周期如下:

从Activity的onCreateonDestory的期间都是存活的
ViewModel的生命周期

Fragment间共享数据

1、Activity中一般有多个Fragment,也都涉及到数据共享的问题。

例如: 第一个Fragment选中一个列表中的Item,第二个Fragment展示这个选中的数据
ViewModel: 共享的数据

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

    public void select(Item item) {
        selected.setValue(item);
    }

    public LiveData<Item> getSelected() {
        return selected;
    }
}

FragmentA: 选中某一个Item

public class MasterFragment extends Fragment {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 1. 获取到ViewModel
        final SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);

        // 2. 点击后,将选中的Item设置到ViewModel中
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}

FragmentB: 展示选中的Item

public class DetailFragment extends Fragment {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 1. 获取到同一个ViewModel
        SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);

        // 2. 监听“Item”,一旦发生改变(表明选中了一个Item),展示该选中的数据
        model.getSelected().observe(this, { item ->
           // Update the UI.
        });
    }
}

2、利用ViewModel共享Fragment的数据有什么好处?

  1. Activity不需要关心相关的任何事情
  2. Fragment不需要知道其他有哪些Fragment也在依赖这些数据
  3. 当某个Fragment结束的时候,ViewModel能自动处理好生命周期相关的事务

ViewModel替代Loaders

1、ViewModel替换那些用来保持UI中的数据和数据库同步的Loaders

  1. 利用ViewModel可以将Loaders和UI的逻辑相分离

2、ViewModel进行UI和数据库数据同步的方案

  1. ViewModel确保在设备配置改变时,数据依然存在
  2. Room在数据库改变时通知LiveData
  3. LiveData察觉到改变时,通知UI更新相应的数据

知识扩展

Fragment的setRetainInstance

1、通过Fragment的setRetainInstance(true)实现Configuration Changes时,数据依然存活的特性。

  1. Fragment调用setRetainInstance(true)后,Fragment实例在配置改变如屏幕旋转后依旧存活
  2. 不会再触发onCreate
  3. 其他的如onAttach()、onActivityCreated()依旧会触发

参考资料

  1. 官方文档: ViewModel
  2. 如何在设备设置改变时,保存、持久化、管理数据?
  3. 官方Android APP 架构指导手册
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猎羽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值