Android Architecture Components Part2:LiveData
感谢你的再次光临,欢迎来到Android Architecture Components(ACC)系列文章。上篇文章我们一起讨论了Room,通过Room我们能够方便的操作App的数据库。如果你的App对本地数据库有所依赖的话,Room你值得拥有。
今天这篇文章继续上篇文章的步伐,让我们一起来全面了解ACC另一强大的组件LiveData。相信你马上会喜欢上她!???
简述
LiveData是一种可观测数据容器,它会在数据变化时通知观测器,以便更新页面;同时它具备生命感知能力,可以实时观察Activity/Fragment的生命周期状态。
既然它是可观察数据容器与具备生命感知能力,那么它的优点也很明显,可以归纳与以下几点
- 确保ui跟随数据更新
- 具备生命感知能力从而减少内存泄露
- 防止异常crashs
- 无需管理绑定者的生命周期
- ui获取的数据都是最近最终的更新数据
使用场景
当我们要监听某一个数据的变化时,LiveData将大显身手。例如界面数据的更新,当数据发生变化时,我们要通知界面进行更新ui,这时我们可以使用LiveData在当前Activity/Fragment中对该数据注册一个观察者,实时监听数据的任何改动。每一次改动LiveData都会发送通知给观察者。
另一方面,LiveData感知界面的生命周期,所以只有在界面生命周期的STARTED或者RESUMED状态才会通知观察者。如果你一直处于后台且数据一直在变化,LiveData是不会发生通知,只有在界面再一次回到前台,这时LiveData才会发生通知且只会发送一次,数据的更新取的是最后一次的变化数据。这样可以有效的避免内存泄露与ui不存在时导致的NullPointerException
使用
首页我们需要在我们的app下的build.gradle中添加如下依赖代码
dependencies {def lifecycle_version = "1.1.1"// ViewModel and LiveDataimplementation "android.arch.lifecycle:extensions:$lifecycle_version"// alternatively - just LiveDataimplementation "android.arch.lifecycle:livedata:$lifecycle_version"annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
}
然后我们就能正式使用LiveData,看如下代码:
class ContactsViewModel(application: Application, private val defTitle: String = "Contacts") : AndroidViewModel(application) {val message: MutableLiveData<String> by lazy { MutableLiveData<String>() }val contactsList: MutableLiveData<List<ContactsModel>> = MutableLiveData()fun getContacts(refresh: Boolean): LiveData<List<ContactsModel>> {message.value = ""if (refresh) {getDataFromRemote()} else if (contactsList.value == null || contactsList.value?.size ?: 0 <= 0) {message.value = "数据请求中,请稍后!"if (mLocalData.isEmpty()) {getDataFromLocal()}}return contactsList}private fun getDataFromLocal() {val runnable = Runnable {val dao = mContactsDao.getAllContacts()if (dao.isNotEmpty()) {contactsList.postValue(dao)} else {getDataFromRemote()}}mExecutors.disIoExecutor.execute(runnable)}private fun getDataFromRemote() {Handler().postDelayed({contactsList.value = mRemoteDatamLocalData = mRemoteDatasaveContacts(mRemoteData)Thread(Runnable {title.postValue("Remote Contacts")}).start()message.value = "数据加载完成~"}, MDELAY_MILLIS)}
}
首先我们使用MutableLiveDat对我们所需要的数据进行了包裹,MutableLiveData它继承与LiveData,暴露了postValue()与setValue()方法。一旦MutableLiveData所包裹的数据发生变化,我们可以通过postValue()(asynchronously)与setValue()(synchronously)来设置值与发送通知,告诉观察者数据已经改变。
在getDataFromLocal()方法中,我们使用了Room来操作数据库,同时直接通过返回LiveData数据类型的数据,使得Room与LiveData完美结合。
所以我们再来看看观察者的代码:
class ContactsActivity : AppCompatActivity() {private lateinit var mViewModel: ContactsViewModeloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_contacts_layout)setupViewModel()}private fun setupViewModel() {mViewModel = ViewModelProviders.of(this, ContactsFactory.getInstance(application))[ContactsViewModel::class.java]//active STARTED、RESUMEDmViewModel.getContacts(true).observe(this,Observer {//todo ...})mViewModel.message.observe(this,Observer {//todo ...})}
}
我们为所需要观察的数据添加了observer方法,该方法第一个参数是LifecyleOwner,以便让LiveData具有生命感知能力,这里要感知的是ContactsActivity,所以传入this即可。第二个参数是一个回调方法,一旦数据发生变化它的onChanged()就会回调,并将数据带回,这样界面就能实时更新数据。
最后由于LiveData是生命感知的所以我们也无需担心他的register/unregister
Extend
我们已经知道LiveData会对处于STATERD或者RESUMED状态进行发送通知,如果该状态下存在observer,由无到有,我们称之为active,反正称之为inactive。如果我们能够知道何时为active与何时为inactive,那么我们就可以实现自己的LiveData。为了解决这个问题,LiveData提供了两个方法,分别为onActive()与onInactive()。
例如我们想为一个监听器实现生命感知能力,可以进行如下操作
public class StockLiveData extends LiveData<BigDecimal> {private static StockLiveData sInstance;private StockManager mStockManager;private SimplePriceListener mListener = new SimplePriceListener() {@Overridepublic void onPriceChanged(BigDecimal price) {setValue(price);}};@MainThreadpublic static StockLiveData get(String symbol) {if (sInstance == null) {sInstance = new StockLiveData(symbol);}return sInstance;}private StockLiveData(String symbol) {mStockManager = new StockManager(symbol);}@Overrideprotected void onActive() {mStockManager.requestPriceUpdates(mListener);}@Overrideprotected void onInactive() {mStockManager.removeUpdates(mListener);}
}
一旦observer由无到有,那么我们就在onActive()方法中进行监听器的注册。observer由有到无,我们可以在onInactive()中进行注销。这样就可以是我们的监听器具备生命感知能力。避免不必要的内存泄露或者一次crash。同时一旦监听器的回调方法生效时,我们又可以通过LiveData的setValue()来对观察者进行数据的更新。所以观察者的代码如下:
public class MyFragment extends Fragment {@Overridepublic void onActivityCreated(Bundle savedInstanceState) {StockLiveData.get(getActivity()).observe(this, price -> {// Update the UI.});}
}
如果细心的话,可以发现上面的StockLiveData已经实现了监听器共享。我们可以在多个界面中使用StockLiveData进行添加observer。例如在Activity中,只要有一个observer,那么它将一直监听数据的变化。
案例:对于App统计需求,一旦涉及到多个页面间的统计参数传递,可以自定义一个扩展LiveData来全局监听参数的传递与变化。
Transform
在通知观察者数据改变之前,如果你想改变LiveData中的值类型,可以使用Transformations
Transformations.map()
获取原有类型中的某个特定的类型值,可以比喻为解包,可以使用map()方法
LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {user.name + " " + user.lastName
});
Transformations.switchMap()
与map对应的是switchMap()方法,这里就是打包。
private LiveData<User> getUser(String id) {...;
}LiveData<String> userId = ...;
LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );
MediatorLiveData
与LiveData相关的还有一个MediatorLiveData,它的作用是:可以同时监听多个LiveData。例如同时监听本地数据与远程数据。
LiveData<List<User>> usersFromDatabase;
LiveData<List<User>> usersFromNetwork;MediatorLiveData<List<User>> usersLiveData = new MediatorLiveData<>();usersLiveData.addSource(usersFromDatabase, newUserList ->usersLiveData.setValue(value));usersLiveData.addSource(usersFromNetwork, newUserList ->usersLiveData.setValue(value));
一旦其中一个发送变化,MediatorLiveData都会发送通知给observer。
是否感觉LiveData很强大呢?那么赶紧行动起来吧,让你的App中数据也具有可观察与生命感知能力。
最后文章中的代码都可以在Github中获取到。使用时请将分支切换到feat_architecture_components
相关文章
Android Architecture Components Part1:Room
Android Architecture Components Part3:Lifecycle
Android Architecture Components Part4:ViewModel
关注
私人博客
Android Architecture Components Part2:LiveData相关推荐
- Android Architecture Components 整理
Android Architecture Components是谷歌在Google I/O 2017发布一套帮助开发者解决Android架构设计的方案. 里面包含了两大块内容: 生命周期相关的Life ...
- 基于 Android Architecture Components 的 MVVM 浅析
0.前言 官方文档永远是最好的学习资料: Android Jectpack Android Jetpack: LiveData 和 Lifecycle 介绍 | 中文教学视频 Android Jetp ...
- 浅谈Android Architecture Components
浅谈Android Architecture Components 浅谈Android Architecture Components 简介 Android Architecture Componen ...
- Android Jetpack Components of LiveData 学习笔记
Android Jetpack Components of Lifecycle 学习笔记 Android Jetpack Components of LiveData 学习笔记 Android Jet ...
- Android Architecture Components
开发者经常面临的问题 Android应用由四大组件构成,各组件可以被独立且无序的调起,用户会在各个App之间来回切换.组件启动后,生命周期会受用户的操作和系统影响,不完全受开发者控制.而由于设备内存问 ...
- Android Architecture Components 之 Room 篇
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VNfFSo5n-1651804572351)(https://user-gold-cdn.xitu.io/2018/4/ ...
- [译] Architecture Components 之 Adding Components to your Project
[目录] 1. Architecture Components 之 Guide to App Architecture 2. Architecture Components 之 Adding Comp ...
- [译] Architecture Components 之 Room Persistence Library
[目录] 1. Architecture Components 之 Guide to App Architecture 2. Architecture Components 之 Adding Comp ...
- Android Jetpack Components of ViewModel 学习笔记
Android Jetpack Components of Lifecycle 学习笔记 Android Jetpack Components of LiveData 学习笔记 Android Jet ...
最新文章
- 王兴和张一鸣和我们的互联网启蒙
- SAP WM MIGO移动类型311转库过账后WM层面产生了Posting Change Notice?
- java节假日api--关于节假日想到的
- 【Android 应用开发】Android 返回堆栈管理 ( 默认启动模式 | 栈顶复用启动模式 | 栈内复用启动模式 | 单实例启动模式 | CLEAR_TOP 标识 )
- 安装 | MatlabR2021bMac链接及Matlabx运行图基本运行代码与图像
- 通俗易懂,C#如何安全、高效地玩转任何种类的内存之Span
- java 返回js_如何基于java或js获取URL返回状态码
- 你真的会用 regexp_replace 吗?
- MOSS之:DataForm Web Part解析
- RocketMQ消息消费源码分析
- 201521123045 《Java程序设计》第7周学习总结
- java把字符串转为日期_Java程序将字符串转换为日期
- 用C写邮箱密码暴力破解器
- 清除html中table标签显示的数据,jquery – 数据清除tbody
- android微信运动页面开发,微信小程序仿微信运动步数排行(交互)
- Android之原始的QQ好友分组实现
- 如何成为一名优秀的技术 Leader?(转)
- VPS一键测试脚本 / 自带结果导出
- python爬取酷狗音乐_Python爬取酷狗音乐
- h5 修改title 微信_iH5中级教程:微信必备,为H5设定标题
热门文章
- 解读2019华为第001号文件:AI时代软件开发的第一要义是可信
- 如何使用charles对Android Https进行抓包
- 未来数据中心的选择:宽带多模光纤(WBMMF)
- debian 8 网桥
- jQuery 中 jQuery(function(){})与(function(){})(jQuery) 的区别
- 【转】VC++ MFC文件的移动复制删除更名遍历操作
- 【新手教程】如何向App Store提交应用
- 数据防泄漏(中文版)
- 互联网绑上美国外交政策战车
- Android 中文API (91) —— GestureDetector