ViewModel+LiveData
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的生命周期:
具体使用
引入ViewModel和LiveData
在build.gradle中添加编译lifecycle.extensions module,该module同时包含ViewModel和LiveData:
compile('android.arch.lifecycle:extensions:1.0.0')
- 构造ViewModel
借用官方提供的例子,去获取一个用户的数据,这里直接引入LiveData构造一个ViewModel.
public class UserProfileViewModel extends ViewModel { ... private User user; private LiveData user; public LiveData getUser() { return user; }}
获取数据
首先通过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官方架构:
更多相关文章
- android获取有线网的Mac地址
- android activity向fragment通信,获取fragment的三种方法
- [置顶] Android中的观察者DataSetObservable和DataSetObserver
- Android(安卓)Json数据转实体类一键转化工具GsonFormat
- SurfaceComposerClient与SurfaceFlinger建立通信流程
- Android(安卓)Camera Hal 的初步实现1
- php脚本生成google play url的下载链接,下载apk并自动反编译后获
- Android(安卓)读取元素的数据
- android mvvm livedata_Android(安卓)MVP && MVVM深度解析