Android在前段时间正式发布 Android 架构组件 1.0 稳定版,里面包含Lifecycles,LiveData,ViewModel,Room。这里主要记录一下LiveData和ViewModel配合使用。

LiveData

LiveData 是一款基于观察者模式的可感知生命周期的核心组件。LiveData 为界面代码 (Observer)的监视对象 (Observable),当 LiveData 所持有的数据改变时,它会通知相应的界面代码进行更新。同时,LiveData 持有界面代码 Lifecycle 的引用,这意味着它会在界面代码(LifecycleOwner)的生命周期处于 started 或 resumed 时作出相应更新,而在 LifecycleOwner 被销毁时停止更新。通过 LiveData,开发者可以方便地构建安全性更高、性能更好的高响应度用户界面

使用LiveData的好处
  • 保证你的UI 能根据数据状态发生改变
  • 不会有内存泄漏
  • 不会因为Activity的stop造成crashes
  • 不用手动去控制生命周期
  • 永远保证数据更新

ViewModel

ViewModel 将视图的数据和逻辑从具有生命周期特性的实体(如 Activity 和 Fragment)中剥离开来。直到关联的 Activity 或 Fragment 完全销毁时,ViewModel 才会随之消失,也就是说,即使在旋转屏幕导致 Fragment 被重新创建等事件中,视图数据依旧会被保留。ViewModels 不仅消除了常见的生命周期问题,而且可以帮助构建更为模块化、更方便测试的用户界面。

ViewModel的作用和好处
  • Activity、Fragment存活期间的数据存储;
  • 独立或与LiveData配合实现代码解耦;
ViewModel的生命周期

ViewModel的生命周期与Lifecycle同步,当Activity /Fragment超出Lifecycle范围(并不是onDestroy()回调),ViewModel连同其包含的数据一起被销毁了。
Activity退栈后(Fragment则是与Activity解除关系后),ViewModel就解除引用关系,准备被系统回收了。下面这张图片更直观的展示了ViewModel的生命周期:

具体使用

  1. 引入ViewModel和LiveData

    在build.gradle中添加编译lifecycle.extensions module,该module同时包含ViewModel和LiveData:

compile('android.arch.lifecycle:extensions:1.0.0')
  1. 构造ViewModel
    借用官方提供的例子,去获取一个用户的数据,这里直接引入LiveData构造一个ViewModel.
public class UserProfileViewModel extends ViewModel {    ...    private User user;    private LiveData user;    public LiveData getUser() {        return user;    }}
  1. 获取数据

    首先通过ViewModelProviders和Activity / Fragment获取ViewModelProvider;
    然后根据ViewModelProvider和自定义ViewModel类获取自定义ViewModel对象;

public class UserProfileFragment extends Fragment {    private static final String UID_KEY = "uid";    private UserProfileViewModel viewModel;    @Override    public void onActivityCreated(@Nullable Bundle savedInstanceState) {        super.onActivityCreated(savedInstanceState);        String userId = getArguments().getString(UID_KEY);         viewModel.getUser().observe(this, user -> {            // update UI        });    }    @Override    public View onCreateView(LayoutInflater inflater,                @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        return inflater.inflate(R.layout.user_profile, container, false);    }}

进行到这一步,基本实现了每一次User数据更新就会回掉刷新UI界面。而且并不需要去实现Fragment的onStop()方法来停止观察数据。因为LiveData是一个有生命周期意识的组件,它不需要我们去手动的停止,而且会在onDestroy()中自动的remove 掉这个观察事件。

另外也并不需要去管屏幕的旋转,因为当屏幕旋转的时候ViewModel会自动保存下当前Fragment的数据和状态。

经过上面的步骤已经将ViewModel和fragment关联起来了,但是并没有真正的通过ViewModel去获取数据。下面记录一下如何通过Retrofit 去获取数据:

public interface Webservice {    /**     * @GET declares an HTTP GET request     * @Path("user") annotation on the userId parameter marks it as a     * replacement for the {user} placeholder in the @GET path     */    @GET("/users/{user}")    Call getUser(@Path("user") String userId);}

新建一个UserRepository

public class UserRepository {    private Webservice webservice;    // ...    public LiveData getUser(int userId) {        // This is not an optimal implementation, we'll fix it below        final MutableLiveData data = new MutableLiveData<>();        webservice.getUser(userId).enqueue(new Callback() {            @Override            public void onResponse(Call call, Response response) {                // error case is left out for brevity                data.setValue(response.body());            }        });        return data;    }}

就像官方描述的UserRepository并不是必须的,把它抽象出来,这样ViewModel就不知道数据是通过Webservice来获取的,好处就是which means we can swap it for other implementations as necessary.

最后将UserRepository和ViewModel关联起来,修改ViewModel:

public class UserProfileViewModel extends ViewModel {    private LiveData user;    private UserRepository userRepo;    @Inject // UserRepository parameter is provided by Dagger 2    public UserProfileViewModel(UserRepository userRepo) {        this.userRepo = userRepo;    }    public void init(String userId) {        if (this.user != null) {            // ViewModel is created per Fragment so            // we know the userId won't change            return;        }        user = userRepo.getUser(userId);    }    public LiveData getUser() {        return this.user;    }}

总结

就这样一个完整的ViewModel+LiveData的例子就完成了。

ViewModel+LiveData可以很方便的抽象出数据层和业务层,快速解耦。
通过Demo,以及LiveData、ViewModel同处一个module,可以看出官方非常建议两者搭配使用。再配合以往的Data-Binding,可以快速搭建起一套简易的MVVM业务体系。

最后通过一张图可以大概的了解下Android官方架构:

更多相关文章

  1. android获取有线网的Mac地址
  2. android activity向fragment通信,获取fragment的三种方法
  3. [置顶] Android中的观察者DataSetObservable和DataSetObserver
  4. Android(安卓)Json数据转实体类一键转化工具GsonFormat
  5. SurfaceComposerClient与SurfaceFlinger建立通信流程
  6. Android(安卓)Camera Hal 的初步实现1
  7. php脚本生成google play url的下载链接,下载apk并自动反编译后获
  8. Android(安卓)读取元素的数据
  9. android mvvm livedata_Android(安卓)MVP && MVVM深度解析

随机推荐

  1. Android(安卓)Setting中添加解除屏幕锁选
  2. android之File
  3. Android(安卓)Manager之SensorManager(传
  4. android 自定义TextView中Html超链接点击
  5. 我今天的面试题,注册广播有几种方式,这些方
  6. android WebView 启用javaScript
  7. Android发送短信
  8. Android(安卓)Mount Daemon
  9. Android(安卓)Button example
  10. android 沉浸式状态栏的三种方法