美文网首页
ViewModel、LiveData的“数据驱动方式”编程

ViewModel、LiveData的“数据驱动方式”编程

作者: JohnYuCN | 来源:发表于2022-04-28 19:35 被阅读0次
  • MV-VM模式,日益在大前端设计占据主流,Android原生开发JetPack库,为此打造了一套基础设施API,并在此基础上打造一套完整的UI生态, 本文结合ViewModel、LiveData组合Fragment,完成一个基础的“基于数据驱动方式”应用系统。
    重点:本文所做的全部努力是:如何pojo对象打造成为一个“响应式”对象,即数据(Model)的修改,将会直接更新视图(Model)
    本案例完整代码见:https://gitee.com/johnyucn525/view-model-live-data-demo.git
    完成图

一、pojo 如何变成“响应式对象”

  1. User对象
/**
 * 一般的pojo对象,并不具备任何的"响应式特性",无法使用"数据驱动模式"
 */
public class User {
    private String uname;
    public String getUname() {
        return uname;
    }
    public void setUname(String uname) {
        this.uname = uname;
    }
}
  1. 将User对象变成主题(Subject)

(1) 扮演 Subject 角色的类是: androidx.lifecycle.LiveData,可以在【某个地方1】如下编码:

//...获取user对象的过程略
MutableLiveData<User> liveUser=new MutableLiveData<>();
liveUser.setValue(user);

此时liveUser,就是我们需要的主题(Subject)对象。

下面有两个问题没有解决:

  • 如何注册观察者
  • 如何保证此对象在UI控制器(即:Activity 和 Fragment ) 生存期中,保证可以随时使用一个“单例保活”的 LiveData。

(2)注册观察者:

在【某个地方 2】如下编码,完成将一个观察者(Observer)注册到 liveUser

liveUser.observe(LifecycleOwner, Observer)

LifecycleOwner 它可以Activity 或 Fragment 的实例。
Observer 是一个函数式接口,其可以使用 Lamda 完成,而Lamda 的参数就是 pojo 对象User,当我们在 【某个地方 3】对 liveUser 进行了修改时(liveUser.setValue(newUser)),Observer 就会发生回调处理,在这个回调处理中,我们可以编写Model 和 View 的 Bind 逻辑,从而完成“数据驱动方式”编程。

(3) “单例保活”的 LiveData,获取方法
答案是: 使用 androidx.lifecycle.ViewModel

我们可以扩展一个自定义的 ViewModel 类,对LiveData进行包装,此时即为 【某个地方1】:

package cn.johnyu.a0428;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class UserViewModel extends ViewModel {
    // MV-VM中的 Model 就在此处
    private MutableLiveData<User> liveUser=new MutableLiveData<>();
    //此Api调用时,将会通知给Observer
    public void setUser(User user){
        liveUser.setValue(user);
    }
    //调用此API,获取LiveData,并注册观察者
    public MutableLiveData<User> getUser(){
        return liveUser;
    }
}

随后在Activity或Fragment的生命周期方法中(一般会是onCreateView),使用工厂方法(注意不能是new方法)获取ViewModel对象,此方法会缓存ViewModel对象,即:只有第一次才进行实例化的工作,以后每次只是获取同一个单例对象,此对象只有在相应的Activity或Fragment销毁时才销毁;本例,此方法会在消息发布和消息订阅的两个Fragment中进行调用,而获取的是一个与MainActivity相关联的ViewModel

  • 在ListFragment中:
//消息发布的Fragment
public class ListFragment extends Fragment {
    private UserViewModel userViewModel;
    public ListFragment() {
        super(R.layout.fragment_list);
    }
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view,savedInstanceState);
        //跟随MainActivity的单例模式的ViewModel,在Activity的Destroy后,自动调用ViewModel的onDestroy进行数据的清理
        userViewModel =new ViewModelProvider(requireActivity()).get(UserViewModel.class);

        //其它代码.....
  • 在DetailFragment中:
//消息订阅的Fragment
public class DetailFragment extends Fragment {
    private UserViewModel userViewModel;
    private TextView textView;
    public DetailFragment() {
        super(R.layout.fragment_detail);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        textView=view.findViewById(R.id.uname);

        //此处获取的是同一个与MainActivity相关的ViewModel
        userViewModel =new ViewModelProvider(requireActivity()).get(UserViewModel.class);
        
        //其它代码。。。

现在我们就可以利用这个“保活”的ViewModel来获取“保活”的LiveData了,即:我们把pojo通过层层包装变成了“响应式对象”了。

二、响应式对象的使用:

在ListFragment中修改主题,完成消息发布【某个地方 3】:

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view,savedInstanceState);
        //跟随MainActivity的单例模式的ViewModel,在Activity的Destroy后,自动调用ViewModel的onDestroy进行数据的清理
        userViewModel =new ViewModelProvider(requireActivity()).get(UserViewModel.class);

        //其它代码...
        //为"详细信息"按钮添加事件处理器
        view.findViewById(R.id.detailBtn).setOnClickListener(event->{
            User user=new User();
            user.setUname("john"+Math.random());
            //消息发布:即,修改主题(向主题的所有观察者发布消息)
            userViewModel.setUser(user);
        });
    }

在DetailFragment中订阅主题,并完成回调修改视图【某个地方 2】:

@Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        textView=view.findViewById(R.id.uname);

        //此处获取的是同一个与MainActivity相关的ViewModel
        userViewModel =new ViewModelProvider(requireActivity()).get(UserViewModel.class);

        //其它代码。。。
        //订阅主题,完成回调修改视图,完成了数据与视图的绑定工作,以后只要user进行了修改,回调会自动进行
        userViewModel.getUser().observe(getViewLifecycleOwner(), user -> {
            textView.setText(user.getUname());
        });
    }

相关文章

网友评论

      本文标题:ViewModel、LiveData的“数据驱动方式”编程

      本文链接:https://www.haomeiwen.com/subject/xqedyrtx.html