Android ViewModel的使用

ViewModel的作用是为界面准备数据,数据的获取操作(如网络请求)或者一些数据处理可以在该类中编写方法,减少在Activity的代码。

ViewModel里面的数据可以分为以下三类。

  1. 普通数据,只是负责保存数据,无特别作用,可当做普通类来用
    public class DataViewModel extends ViewModel {
        public String name;
        public int age;
    }

     

  2. 与LiveData结合使用。MutableLiveData的取/赋值方法分别为getValue(),setValue(),如果不在主线程,用postValue()。关于LiveData可以看我的另外一篇文章Android LiveData的使用
    public class DataViewModel extends ViewModel {
        private MutableLiveData<String> name;
        private MutableLiveData<Integer> age;
        public MutableLiveData<String> getName() {
            if (name == null) {
                name = new MutableLiveData<String>();
                //获取初始值的操作,否则默认为""。
            }
            return name;
        }
        public MutableLiveData<Integer> getAge() {
            if (age == null) {
                age = new MutableLiveData<Integer>();
                //获取初始值的操作,否则默认为0。
            }
            return age;
        }
    }

     

  3. 与DataBinding结合使用,ObservableField自带get/set方法。DataBinding的使用可以看我另外一篇文章Android DataBinding的简单使用
    /**
     *  什么时候用MutableLiveData?什么时候用ObservableField?
     *      双向绑定看起来很便利,不需关注值的变化去更新视图。但实际业务大多数要对输入的值进行校验并做一些处理,不仅仅只是把值赋给实体对象。
     *  个人感觉用MutableLiveData比较灵活,有些时候控件是动态添加进布局里的,这种时候很难用ObservableField进行赋值(也很难进行逻辑处理),
     *  而使用MutableLiveData,在onChanged方法里面我想更新什么就更新什么(逻辑写在activity中思路也比较清晰)
     *      结论:
     *  1、在不用处理数据(即用户输入什么就是什么,不涉及逻辑处理)/只用做数据显示(并且页面布局都由XML写,不涉及动态添加控件)的情况下,使用ObservableField比较方便
     *  2、其余情况用MutableLiveData比较灵活
     */
    public class DataViewModel extends ViewModel {
        public final ObservableField<String> name = new ObservableField<>();
        public final ObservableField<Integer> age = new ObservableField<>();
    }

     

这三种类型可以分开使用,也可以看需求混合搭配使用。官方提供了以下的创建方法来获取ViewModel的实体对象(我发布这篇文章时,中文官网展示的方法还是旧版的,以下的代码已经是修改后的最新方法,旧版方法已抛弃。无法保证以后版本更新会不会有新的创建方法,如以后发现代码报错,可去官网看最新代码)。

  1. 这种方法获取的ViewModel,仅在Activity第一次创建的时候会进行创建,之后将会复用之前创建好的ViewModel,可用于页面状态保存。
    public class MyActivity extends AppCompatActivity {
          // Create a ViewModel the first time the system calls an activity's onCreate() method.
         // Re-created activities receive the same MyViewModel instance created by the first activity.
        public void onCreate(Bundle savedInstanceState) {
            ViewModelProvider.Factory factory  = ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication());
            DataViewModel dataViewModel = new ViewModelProvider(this, factory).get(DataViewModel.class);
        }
    }
  2. 这种方法获取的ViewModel,每次都会进行重新创建(个人感觉跟直接用new DataViewModel()没什么不同,有不同观点的欢迎指出)。
    public class MyActivity extends AppCompatActivity {
        public void onCreate(Bundle savedInstanceState) {
            ViewModelProvider.Factory factory  = ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication());
            DataViewModel dataViewModel = factory.create(DataViewModel.class);
        }
    }

为了统一管理ViewModel,我写了下面这个工具类,所有ViewModel都可以通过这个类的方法来创建(也可以把这几个方法放在application的类里)。getPrivateViewModel()对应上面的方法1。getViewModel()对应上面的方法2,并存放在一个静态map中,可实现在多个页面公用同一个ViewModel的数据。

import android.app.Activity;
import android.app.Application;

import java.util.HashMap;
import java.util.Map;

import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner;


/**
 * ViewModel工具类
 */
public class ViewModelUtils {
    private static Map<Class, ViewModel> viewModelMap = new HashMap<>();
    /**
     * 获取全局唯一的ViewModel
     * 常用与跨页面修改数据(并且需要刷新显示),比如在某个页面对该ViewModel里的MutableLiveData进行了observe,
     * 无论在哪里修改ViewModel里面的MutableLiveData的值,这个页面都会收到通知(页面在活跃状态下马上收到,非活跃状态下将在变为活跃状态的那一刻收到),收到通知后调用onChanged()方法(一般是刷新视图)
     * @param application  本项目所设置使用的application实体
     * @param viewModelClass ViewModel对应的类
     * @param <T>
     * @return
     */
    public static <T extends ViewModel> T getViewModel(Application application, Class<T> viewModelClass){
        if (viewModelMap.containsKey(viewModelClass)){
            return  (T) viewModelMap.get(viewModelClass);
        }
        T t = ViewModelProvider.AndroidViewModelFactory.getInstance(application).create(viewModelClass);
        viewModelMap.put(viewModelClass, t);
        return t;
    }
    public static <T extends ViewModel> T getViewModel(Fragment fragment, Class<T> viewModelClass){
        return getViewModel(fragment.getActivity(),viewModelClass);
    }
    public static <T extends ViewModel> T getViewModel(Activity activity, Class<T> viewModelClass){
        return getViewModel(activity.getApplication(),viewModelClass);
    }

    /**
     * 获取只在本页面唯一的ViewModel(一般用于保存页面状态,比如横竖屏切换后要恢复状态)
     * @param application 本项目所设置使用的application实体
     * @param viewModelClass ViewModel对应的类
     * @param owner  一般就是AppCompatActivity或Fragment
     * @return
     */
    public static <T extends ViewModel> T getPrivateViewModel(Application application, Class<T> viewModelClass,ViewModelStoreOwner owner){
        ViewModelProvider.Factory factory  = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
        return new ViewModelProvider(owner, factory).get(viewModelClass);
    }
    public static <T extends ViewModel> T getPrivateViewModel(Activity activity, Class<T> viewModelClass,ViewModelStoreOwner owner){
        return getPrivateViewModel(activity.getApplication(),viewModelClass,owner);
    }
    public static <T extends ViewModel> T getPrivateViewModel(Fragment fragment, Class<T> viewModelClass,ViewModelStoreOwner owner){
        return getPrivateViewModel(fragment.getActivity(),viewModelClass,owner);
    }
}

 

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值