Android收藏集系统知识Android专题

ViewModel和LiveData的高效使用

2019-02-22  本文已影响297人  几行代码

ViewModel是谷歌的组建架构AAC(Android Architecture Components)中的组件。
ViewModel类是被设计用来以可感知生命周期的方式存储和管理 UI 相关数据,ViewModel中数据会一直存活(持久化)即使 activity configuration发生变化,比如横竖屏切换的时候。

我们来看看ViewModel的生命周期:


ViewModel的生命周期

由上图可知,ViewModel 生命周期是贯穿整个 Activity 生命周期,包括 Activity 因旋转造成的重新创建,直到 Activity 真正意义上销毁后才会结束。既然如此,用来存放数据再好不过了。

在使用过程中ViewModel一般都是结合LiveData来使用的,这样还能实现数据的异步回调(因为使用ViewModel不用去考虑生命周期,所以能很好地避免一些耗时的异步回调,判断Activity或者Fragment是否存在等问题)并解耦,由于它数据的持久化,可以实现多个fragment之间共享数据:
看一个官网的例子:

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


public class MasterFragment extends Fragment {
    private SharedViewModel model;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}

public class DetailFragment extends Fragment {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        model.getSelected().observe(this, { item ->
           // Update the UI.
        });
    }
}

上面这是 一个Activity 与其内部的 fragment 可以共用一个ViewModel的案例。

总结:

来看一个简单的demo:

/**
 * 基础ViewModel类,管理LiveData
 */
public class BaseViewModel extends ViewModel {
    private Map<String, MutableLiveData> maps;

    /**
     * 构造函数(在ViewModelProvider里通过class.newInstance创建实例)
     */
    public BaseViewModel() {
        maps = new ConcurrentHashMap<>();  //初始化集合(线程安全)
    }

    /**
     * 通过指定的数据实体类获取对应的 LiveData 类
     */
    protected <T> MutableLiveData<T> get(Class<T> clazz) {
        return get(null, clazz);
    }

    /**
     * 通过指定的key或者数据实体类获取对应的 LiveData 类
     */
    protected <T> MutableLiveData<T> get(String key, Class<T> clazz) {
        String keyName;
        if (TextUtils.isEmpty(key)) {
            keyName = clazz.getCanonicalName();
        } else {
            keyName = key;
        }
        MutableLiveData<T> mutableLiveData = maps.get(keyName);
        // 判断集合是否已经存在 LiveData 对象,若存在就返回
        if (mutableLiveData != null) {
            return mutableLiveData;
        }
        // 如果 Map 集合中没有对应实体类的 LiveData 对象,就创建并添加至集合中
        mutableLiveData = new MutableLiveData<>();
        assert keyName != null;
        maps.put(keyName, mutableLiveData);
        return mutableLiveData;
    }

    /**
     * 在对应的FragmentActivity销毁之后调用
     */
    @SuppressWarnings("unchecked")
    @Override
    protected void onCleared() {
        super.onCleared();
        if (maps != null) {
            maps.clear();
        }
    }
}
public class DemoViewModel extends BaseViewModel {
    // 获取 Person 对象对应的 MutableLiveData
    MutableLiveData<Person> getPersonMutableLiveData() {
        return get(Person.class);
    }
}
/**
     * 创建ViewModel对象
     * 在Activity或Fragment需要获取对应的 ViewModel 的时候调用
     * @param clazz 
     * @return 对应的 T 的 ViewModel
     * 泛型中的限定,必须是ViewModel的子类
     */
    public <T extends ViewModel> T get(Class<T> clazz) {
        return viewModelProvider.get(clazz);
    }

    /**
     * 初始化 ViewModelProvider 对象
     * 建议在Activity初始化的时候执行
     * @return ViewModelProvider
     */
    private ViewModelProvider getViewModelProvider() {
        return ViewModelProviders.of(this);
    }
@Route(path = "/test/demo")
public class DemoActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        DemoViewModel demoViewModel = get(DemoViewModel.class);
        MutableLiveData<Person> personMutableLiveData = demoViewModel.getPersonMutableLiveData();
        // 1.添加数据更改监听器  监听数据的回调
        personMutableLiveData.observe(this, new Observer<Person>() {
            @Override
            public void onChanged(@Nullable Person person) {
                Log.e("DemoActivity = ", "DemoActivity中接收person:" + person.toString());
                Log.e("DemoActivity = ", "线程 = :" + Thread.currentThread().getName());  // 打印结果主线程
            }
        });
    }

    public void onClick(View view){
        new Thread(new Runnable() {
            @Override
            public void run() {
                getData();
                Log.e("DemoActivity = ", "线程 *****  &&&&& = :" + Thread.currentThread().getName());
            }
        }).start();
    }

    // 更改数据
    public void getData() {
        Person person = new Person();
        person.setName("Jack");
        person.setSex("男");
        DemoViewModel demoViewModel = get(DemoViewModel.class);
        MutableLiveData<Person> personMutableLiveData = demoViewModel.getPersonMutableLiveData();
        //同步更改setValue  ;  异步更改postValue
        personMutableLiveData.setValue(person);
//        personMutableLiveData.postValue(person);  // 添加数据
    }
}

通过上面的案例大家应该知道怎么使用了,接下来我们进阶使用一下:
先给大家画张图:


进阶使用图

先来创建几个base基础类:

/**
 * 在生命周期的某个时刻取消订阅。
 * 一个很常见的模式就是使用CompositeSubscription来持有所有的Subscriptions,然后在onDestroy()或者onDestroyView()里取消所有的订阅
 */
public abstract class BaseDataModel {

    // 可以缓解Rx内存占用不能释放的问题
    private CompositeSubscription mCompositeSubscription;

    public BaseDataModel() {

    }

    // 添加订阅
    protected void addSubscribe(Subscription subscription) {
        if (mCompositeSubscription == null) {
            mCompositeSubscription = new CompositeSubscription();
        }
        mCompositeSubscription.add(subscription);
    }

    // 移除订阅
    public void unSubscribe() {
        if (mCompositeSubscription != null && mCompositeSubscription.hasSubscriptions()) {
            mCompositeSubscription.clear();
        }
    }
}
public class BaseViewModel<T extends BaseDataModel> extends AndroidViewModel {

    public MutableLiveData<String> loadState; // 网络加载状态的 LiveData

    public T mDataModel;

    public BaseViewModel(@NonNull Application application) {
        super(application);
        loadState = new MutableLiveData<>();
        mDataModel = DemoUtil.getNewInstance(this, 0);
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        if (mDataModel != null) {
            mDataModel.unSubscribe();  // 清除所有订阅 释放内存 (Rx))
        }
    }
}
public abstract class BaseLifecycleFragment<T extends BaseViewModel> extends BaseFragment {

    protected T mViewModel;

    @Override
    public void initView() {
        mViewModel = createViewModel(this, (Class<T>) DemoUtil.getInstance(this, 0));
        if (null != mViewModel) {
            MutableLiveData loadState = mViewModel.loadState;
            loadState.observe(this, observer);
            dataObserver();
        }
    }

    /**
     * 创建 自定义的 ViewModel
     */
    protected <T extends ViewModel> T createViewModel(Fragment fragment, @NonNull Class<T> modelClass) {
        ViewModelProvider viewModelProvider = ViewModelProviders.of(fragment);
        return viewModelProvider.get(modelClass);
    }

    /**
     *  LiveData 观察者回调实现的方法
     */
    protected abstract void dataObserver();

    // lifecycle 中 liveData的监听者
    protected Observer<String> observer = new Observer<String>() {
        @Override
        public void onChanged(@Nullable String state) {
            if (!TextUtils.isEmpty(state)) {
                if (StateConstants.ERROR_STATE.equals(state)) {
                    showToast("加载错误");
                } else if (StateConstants.NET_WORK_STATE.equals(state)) {
                    showToast("网络不好,请稍后重试");
                } else if (StateConstants.LOADING_STATE.equals(state)) {
                    showToast("加载中");
                } else if (StateConstants.SUCCESS_STATE.equals(state)) {
                    showToast("加载成功");
                }
            }
        }
    };
}

工具类:

public class DemoUtil {
    public static <T> T getNewInstance(Object object, int i) {
        if(object!=null){
            try {
                return ((Class<T>) ((ParameterizedType) (object.getClass()
                        .getGenericSuperclass())).getActualTypeArguments()[i])
                        .newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassCastException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    // 获取泛型类型
    public static <T> T getInstance(Object object, int i) {
        if (object != null) {
            return (T) ((ParameterizedType) object.getClass()
                    .getGenericSuperclass())
                    .getActualTypeArguments()[i];
        }
        return null;
    }

    // 检查引用是否为空
    public static @NonNull
    <T> T checkNotNull(final T reference) {
        if (reference == null) {
            throw new NullPointerException();
        }
        return reference;
    }
}
public interface CallBack<T> {
    // 没网络
    void onNoNetWork();
    // 成功
    void onNext(T t);
    // 失败
    void onError(String e);
}

准备工作做好了接下来看如何使用:

/**
 * 网络请求和数据库的操作
 * ApiDataModel 这个类中主要创建 serviceApi 接口
 */
public class HomeDataModel extends ApiDataModel {

    public void requestNetWorHomekData(CallBack listener) {
        Observable<HomeResponse> homeResponseObservable = serviceApi.requestHomeData();
        addSubscribe(
                homeResponseObservable
                        .compose(RxSchedulers.io_main())
                        .subscribe(new RxSubscriber<Object>() {

                            @Override
                            protected void onNoNetWork() {
                                super.onNoNetWork();
                                listener.onNoNetWork();
                            }

                            @Override
                            public void onSuccess(Object o) {
                                listener.onNext(o);
                            }

                            @Override
                            public void onFailure(String msg) {
                                listener.onError(msg);
                            }
                        }));
    }
}
/**
 * 业务逻辑处理
 */
public class HomeViewModel extends NetWorkBaseViewModel<HomeDataModel> {

    public HomeViewModel(@NonNull Application application) {
        super(application);
    }

    private MutableLiveData<HomeResponse> homeMutableLiveData;  // 存储首页数据的 MutableLiveData

    public MutableLiveData<HomeResponse> getHomeMutableLiveData(){
        if (homeMutableLiveData == null) {
            homeMutableLiveData = new MutableLiveData<>();
        }
        return homeMutableLiveData;
    }

    // 发起网络请求
    public void getRequestHomeData() {

        mDataModel.requestNetWorHomekData(new CallBack<Object>() {
            @Override
            public void onNoNetWork() {
                Log.e("HomeViewModel 错误 = ", "网络异常");
                loadState.postValue(StateConstants.NET_WORK_STATE);
            }

            @Override
            public void onNext(Object object) {
                if (object instanceof HomeResponse) {
                    HomeResponse homeResponse = (HomeResponse) object;
                    homeMutableLiveData.postValue(homeResponse);
                    loadState.postValue(StateConstants.SUCCESS_STATE);
                }
            }

            @Override
            public void onError(String e) {
                Log.e("HomeViewModel 错误 = ", e);
            }
        });
    }
}
public class HomeFragment extends BaseLifecycleFragment<HomeViewModel> {
  
    public static HomeFragment newInstance() {
        return new HomeFragment();
    }

    @Override
    protected void dataObserver() {
        mViewModel.getHomeMutableLiveData().observe(this, new Observer<HomeResponse>() {
            @Override
            public void onChanged(@Nullable HomeResponse homeResponse) {
                showData(homeResponse);
            }
        });
    }

    /**
     * 列表展示数据
     */
    private void showData(HomeResponse homeResponse) {
        Log.e("HomeFragment = ",homeResponse.toString());
    }

    @Override
    protected View initLayout(LayoutInflater inflater, ViewGroup container) {
        return inflater.inflate(R.layout.activity_target, null);
    }

    @Override
    public void initView() {
        super.initView();
    }

    @Override
    protected void initData(Bundle savedInstanceState) {
        mViewModel.getRequestHomeData();
    }
}

运行起来打印数据:

数据
网络请求是用的 Retrofit + OkHttp,具体怎么使用:
Retrofit:https://www.jianshu.com/p/dac9a1c02525
OkHttp:https://www.jianshu.com/p/500abf06f447

这样只要DataModel中数据一变化,View中就可以立即监听到数据变化,做出相应操作。

对这个方法的具体解释:

public static <T> T getInstance(Object object, int i) {
        if (object != null) {
            return (T) ((ParameterizedType) object.getClass()
                    .getGenericSuperclass())
                    .getActualTypeArguments()[i];
        }
        return null;
    }

关于怎么获取泛型中参数类型的分析:https://www.jianshu.com/p/27772c32fa41

上一篇下一篇

猜你喜欢

热点阅读