android 新的view,Android最新架构之感受LiveData 与 ViewModel结合之美

原标题:Android最新架构之感受LiveData 与 ViewModel结合之美

亲历!给大龄IT人的几点求职建议

作者:唯鹿

来源:https://blog.csdn.net/qq_17766199

LiveData与ViewModel都是Android官方架构组件(Android Architecture Components)之一。

1.前言

虽说这篇是说LiveData与ViewModel,但是或多或少都有涉及另外一个组件:Lifecycles。它们连同Room都是在17年谷歌IO大会推出的,当时还是预览版,大致17年底时推出了正式版。到今年的IO大会过后,又增加了许多新成员。

e6f3b9c443d0c15c7628a3164b4c56fd.png

可以看到27.0.0的v7库有依赖Lifecycles。

3d64c023c99224eb212a713c7fa9465d.png

当时Lifecycles有集成进SupportActivity。

d46c464e482e2f734babfd5004cea5ae.png

其实一开始我没有太当回事。。。直到27.1.0以后:

af4eb64523e5e9148a7c9e260267aae1.png

好吧,今天的主角出现了,LiveData与ViewModel。看到这里我觉得是该了解一波了。

顺便看一下截止目前最新的v7:

fc24bd7bd83fa3fb5c1ca4db42ebe3d6.png

发现好多常用的组件分离出了v4包,比如ViewPager、SwipeRefreshLayout,这里就不多说了。

2.优势

LiveData 是一个可以感知 Activity 、Fragment生命周期的数据容器。当 LiveData 所持有的数据改变时,它会通知相应的界面代码进行更新。同时,LiveData 持有界面代码 Lifecycle 的引用,这意味着它会在界面代码(LifecycleOwner)的生命周期处于 started 或 resumed 时作出相应更新,而在 LifecycleOwner 被销毁时停止更新。

上面的描述介绍了LiveData的优点:不用手动控制生命周期,不用担心内存泄露,数据变化时会收到通知。

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

ViewModel的优点也很明显,为Activity 、Fragment存储数据,直到完全销毁。尤其是屏幕旋转的场景,常用的方法都是通过onSaveInstanceState()保存数据,再在onCreate()中恢复,真的是很麻烦。

其次因为ViewModel存储了数据,所以ViewModel可以在当前Activity的Fragment中实现数据共享。

那么LiveData与ViewModel的组合使用可以说是双剑合璧,而Lifecycles贯穿其中。

3.基本使用

这里我们按照官方Demo来简单说明,

1. 数据储存

974c1ed151c46ea90102dedf6784c9af.png

LiveDataTimerViewModel很简单,在初始化时启动一个定时任务,每隔一秒通过postValue方法刷新一下数据。

1d89ec4a19d179761988bce58f588ee0.png

Activity也很简单,创建一个观察者elapsedTimeObserver。当LiveDataTimerViewModel中数据有变化时,它就会接收到最新的数据。当然你的页面要处于STARTED 或者 RESUMED。除非你使用observeForever来观察数据,有兴趣的可以去查看源码来了解实现原理。

mLiveDataTimerViewModel.getElapsedTime().observeForever(elapsedTimeObserver);2. Fragmnet 之间数据共享 public class SeekBarViewModel extends ViewModel { public MutableLiveData seekbarValue = new MutableLiveData<>();}

SeekBarViewModel中存储一个Integer类型的数据。

d8ef5d22738f4228346d96d430df093c.png

8fbc916a87fd071f9966c7c88e911dcd.png

实现效果:

71d574bb96e651d0837871a6327dd1fe.gif

这个页面是上下各有一个Fragment_step5的Fragment,Fragment中各有一个SeekBar。效果是拖动其中的SeekBar,另一边的SeekBar也会随之一样变化。

4.简化使用

这里我写了一个小小的工具库Saber来处理(好吧,猝不及防的广告。。。),使用注解处理器(Annotation Processor)将繁琐的代码自动生成。

首先创建一个类,使用@LiveData注解标记你要保存的数据。注意这里的参数名称,下面会用到。

public class SeekBar { @LiveData Integer value;}

Build – > Make Project 生成代码如下:

24164a3862e0d9f13e0df0ce70197b8d.png

提供了ViewModel的常用操作。setXXX()要在主线程中调用,而postXXX()既可在主线程也可在子线程中调用。一般情况下可以直接使用。比如上面的Fragment例子。简化为:

1acea5a05d05cdcd142267ba8f472305.png

8cf60f27f1f7ec11a18c38e496042d3a.png

默认使用@BindViewModel用于数据储存,如果需要Fragment之间数据共享,需要@BindViewModel(isShare = true),当然也要保证传入相同的key值。默认key值是类的规范名称,也就是包名加类名。

537a0d355dd572b5d5cb325a1a0498ba.png

所以一旦需要互通的Fragment类名或包名不一致,就无法数据共享。这时可以指定key值:@BindViewModel(key = "value")

对于第一个例子我们可以这样使用:

public class LiveDataTimerViewModel extends TimerViewModel {//

Activity如下:

public class ChronoActivity3 extends AppCompatActivity { private TextView textView; @BindViewModel LiveDataTimerViewModel mTimerViewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = this.findViewById(R.id.tv); Saber.bind(this); //

是不是使用起来更加的简洁了,如果一个页面有多个ViewModel可能效果更加的明显。

5.原理

因为实现大量借鉴了butterknife,所以使用方法与butterknife几乎一模一样。是不是想起了 butterknife 的@BindView 与 @OnClick。

其实原理也不复杂,就是生成一个类来帮我们来获取ViewModel并实现数据的变化监听。如下:

public class MainActivity_Providers implements UnBinder { private MainActivity target; @UiThread public MainActivity_Providers(MainActivity target) { this.target = target; init(); } private void init() { target.mTimerViewModel = ViewModelProviders.of(target).get(LiveDataTimerViewModel.class); target.mTimerViewModel.getTime().observe(target, new Observer() { @Override public void onChanged(Long value) { target.setData(value); } }); } @CallSuper @UiThread public void unbind() { MainActivity target = this.target; if (target == null) { throw new IllegalStateException("Bindings already cleared."); } this.target = null; }}

所有代码已上传至Github。希望大家多多点赞支持!有什么问题及建议也可以提Issues,让我们将他慢慢的完善起来。

1 . 正式发布 Android 架构组件 1.0 稳定版

2 .【大揭秘】Android架构组件ViewModel来龙去脉

责任编辑:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Room与LiveDataViewModel结合是为了实现数据持久化、数据观察与界面更的最佳实践。 Room是Google为Android提供的一个持久化数据库解决方案,它简化了数据库操作并提供了编译时检查,同时支持在后台线程中进行数据库访问。LiveData是一种可观察的数据容器,它可以感知生命周期,并在数据变化时自动更ViewModel则负责管理界面相关的数据,并且与Activity或Fragment的生命周期无关,避免了数据丢失或重复请求的问题。 将Room与LiveData结合使用,可以将Room中的数据变化以LiveData的形式暴露出来。这样,在数据库发生变化时,LiveData会自动通知相关观察者进行界面更LiveData还具有自动清理机制,当观察者的生命周期结束时会自动停止数据的更,避免了内存泄漏问题。 而结合ViewModel可以更好地管理界面相关的数据。ViewModel可以在配置改变时(如屏幕旋转)保留数据,并且避免了异步任务导致的内存泄漏。通过在ViewModel中缓存LiveData对象,可以在Activity或Fragment恢复时继续观察数据变化,并保持界面更的一致性。 总结而言,Room与LiveDataViewModel结合可以实现一个可靠、高效、响应式的数据处理框架,使得数据的持久化、观察与界面更变得十分简单。这样的架构设计也有利于代码的维护与扩展,提高了开发效率与用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值