参考
文中部分代码图片引用自文章: Understanding LiveData made simple
LiveData 是什么
LiveData 是一个可观察的数据持有者类。与常规 observable 不同,LiveData 是生命周期感知的,它可以感知他应用程序组件的生命周期,例如 Activity,Fragment 或者 Service。此感知确保 LiveData 仅更新处于活动生命周期状态的应用程序组件观察者。
LiveData 是一个可以在给定生命周期内观察到的数据持有者类。这意味着可以将一个Observer 与一个 LifecycleOwner 添加到一对中,并且只有当对应的LifecycleOwner 处于活动状态时,才会通知这个观察者包装数据的修改。如果LifecycleOwner 的状态是 Lifecycle.state.STARTED 或Lifecycle.state.RESUMED,那么它处于活动状态。通过 observeForever 函数添加的观察者被认为总是处于活动状态,因此总是会被通知修改。对于这些观察者,您应该手动调用 removeObserver 函数移除。
如果生命周期移动到销毁状态,相应的观察者将被自动删除。在 Activity 和 Fragment 中,它们可以安全地观察 LiveData,而不用担心泄漏:当它们被销毁时,将立即取消订阅。
LiveData有三个重要方法
onActive():当LiveData被激活时调用onInactive():当LiveData被取消时调用setValue(T):更新LiveData所持有的数据并通知观察者
LiveData 用于保存 ViewModel 的单个数据字段,但也可以用于以解耦的方式在应用程序中的不同模块之间共享数据。
LiveData 的使用场景
- 保证UI状态和数据的统一:
LiveData采用了观察者设计模式。当生命周期状态改变时,LiveData会通知Observer对象。每次应用程序数据更改时,都会通知观察者对象,从而更新UI。 - 减少内存泄漏:
LiveData能够感知到组件的生命周期,观察者绑定到生命周期对象,并在其相关生命周期被破坏后自行清理。 - 防止崩溃:
LiveData可以防止当Activity销毁后执行未清理的回调时引起崩溃,这是因为组件处于非激活状态时,不会收到LiveData中数据变化的通知。 - 实时更新:组件在前台的时候能够实时收到数据改变的通知,这是可以理解的。当组件从后台到前台来时,
LiveData能够将最新的数据通知组件,这两点就保证了组件中和数据相关的内容能够实时更新。 - 资源共享:通过继承
LiveData类,然后将该类定义成单例模式,在该类封装监听一些系统属性变化,然后通知LiveData的观察者。 - 支持异步:
LiveData提供了两种方法修改值:setValue()、postValue(),其中postValue()支持在子线程中调用。
LiveData 的使用
常用用法
ShareViewModel.kt
class ShareViewModel : ViewModel() {
val clickLiveData = MutableLiveData<String>()
}
MasterFragment.kt
val model = ViewModelProvider(this).get(ShareViewModel::class.java)
class MasterFragment: Fragment() {
private lateinit var viewModel: ShareViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_master, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(activity!!).get(ShareViewModel::class.java)
button.setOnClickListener {
val value = viewModel.clickLiveData.value
viewModel.clickLiveData.value = value?.plus(1) ?: 0
}
}
}
DetailsFragment.kt
class DetailsFragment: Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_details, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val viewModel = ViewModelProvider(activity!!).get(ShareViewModel::class.java)
viewModel.clickLiveData.observe(this, Observer {
textView.text = "${viewModel.clickLiveData.value}"
})
}
}
扩展LiveData - 监听网络状态
class NetworkLiveData(private val context: Context) : LiveData<Int>() {
private val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(p0: Context?, p1: Intent?) {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
val networkInfo = connectivityManager!!.activeNetworkInfo
value = if (networkInfo != null && networkInfo.isAvailable) 1 else 0
}
}
override fun onInactive() {
super.onInactive()
context.unregisterReceiver(broadcastReceiver)
}
override fun onActive() {
super.onActive()
val intentFilter = IntentFilter()
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
context.registerReceiver(broadcastReceiver, intentFilter)
}
companion object {
private lateinit var sInstance: NetworkLiveData
@MainThread
fun get(context: Context): NetworkLiveData {
sInstance = if (::sInstance.isInitialized) sInstance else NetworkLiveData(context.applicationContext)
return sInstance
}
}
}
val networkLiveData = NetworkLiveData(this)
networkLiveData.observe(this, Observer {
value ->
if (value == 1){
Toast.makeText(this, "is work", Toast.LENGTH_LONG).show()
} else{
Toast.makeText(this, "is not work", Toast.LENGTH_LONG).show()
}
})
LiveData转换 - Transformations
Transformations 可以对 LiveData 进行变换操作,它提供了两个操作符 map 和 switchMap 他们的作用都是将一个 LiveData 转换为另一个 LiveData 对象,当一个 LiveData 里的值发生改变时另一个 LiveData 的值也随之发生改变。
在官方文档中对于 map、switchMap 的讲解实在是让人难以理解。有兴趣的可以看下 这篇文章 Understanding LiveData made simple,作者对于这两者的区别和用法都做了详细的讲解。
对于 map 方法来说,它的目的在通过 Function 将 LiveData 参数的值进行转换并根据转换生成的值返回一个新的 LiveData,可以说返回值 LiveData 是由传参 LiveData 生成的。
对于 switchMap 方法来说,返回值 LiveData 和传参 LiveData 之间半毛钱关系也没有,传参 LiveData 可以看做一个开关或者选择器,而新 LiveData 根据选择器返回不同的实例。
下面是文章中的三幅图可用来加深理解:
不使用 Transformations
getLiveDataA().observe(this, changeObserver)

使用 Transformations.map()
Transformations.map(getLiveDataA()) { "A:$it" }

使用 Transformations.switchMap()
Transformations.switchMap(getLiveDataSwitch()) {
switchToB ->
if (switchToB) {
getLiveDataB()
} else {
getLiveDataA()
}
}

可以看到 map 注重的是数据的转换,而 switchMap 注重的是数据的选择,这就是这两者的区别。
MutableLiveData 、MediatorLiveData
LiveData 是一个抽象类,不可以直接使用,但是 Google 为我们提供了两个实现类,如下:
MutableLiveData:可变的LiveData,是我们最常用的LiveData子类。它的实现很简单,就是继承了LiveData然后向外暴露了setValue、postValue方法。MediatorLiveData:它继承自MutableLiveData可以监听多个LiveData数据源,或者调度多个LiveData数据源决定向观察者发送那个LiveData的数据更新。它新增了两个方法addSource、removeSource用于添加和删除LiveData源。
class MediatorLiveDataFragment : Fragment() {
private val changeObserver = Observer<String> { value ->
value?.let { txt_fragment.text = it }
}
override fun onAttach(context: Context?) {
super.onAttach(context)
val mediatorLiveData = MediatorLiveData<String>()
mediatorLiveData.addSource(getliveDataA())
{ mediatorLiveData.value = "A:$it" }
mediatorLiveData.addSource(getliveDataB())
{ mediatorLiveData.value = "B:$it" }
mediatorLiveData.observe(this, changeObserver)
}
// .. some other Fragment specific code ..
}

资源共享
主要是通过单例模式实现的资源共享。
ShareLiveData.kt
class ShareLiveData : LiveData<Int>() {
fun getNewValue() = value
fun setNewValue(newValue: Int) {
value = newValue
}
companion object {
private lateinit var sInstance: ShareLiveData
@MainThread
fun get(): ShareLiveData {
sInstance = if (::sInstance.isInitialized) sInstance else ShareLiveData()
return sInstance
}
}
}
MainActivity.kt
val shareLiveData = ShareLiveData.get()
shareLiveData.observe(this, Observer {
value -> tvNetState.text = "$value"
})
btJumpOther.setOnClickListener {
startActivity(Intent(this, OtherActivity::class.java))
}
OtherActivity.kt
val shareLiveData = ShareLiveData.get()
shareLiveData.observe(this, Observer {
value -> tvNetState.text = "$value"
})
btChangeNetState.setOnClickListener {
shareLiveData.setNewValue(if (shareLiveData.getNewValue() == 1) 0 else 1)
}
LiveData 源码解析
注册 Observer
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
// 如果当前生命周期是DESTROYED,直接return
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
// 这个包装类,做了一件事情,在DESTROYED,移除Observer
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
// 添加在已经Observer,已存在且在Attach上后直接抛异常,也就是不能重复add
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
// 把Wrapper添加到LifecycleOwner上
owner.getLifecycle().addObserver(wrapper);
}
复制代码 Observer 如何被响应:
public interface Observer<T> {
/**
* Called when the data is changed.
* @param t The new data
*/
void onChanged(T t);
}
复制代码触发的起点,很明显是我们在 set/postValue 的时候:
@MainThread
protected void setValue(T value) {
// 记住这个值,它是用来表示数据是否发生变化的
mVersion++;
mData = value;
dispatchingValue(null);
}
void dispatchingValue(@Nullable ObserverWrapper initiator) {
// 省略部分代码
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
// 往里走
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
// 省略部分代码
}
private void considerNotify(ObserverWrapper observer) {
// 如果observer不在活动期,则直接return。也就是上述说observer不在前台,将不会接受回调。
if (!observer.mActive) {
return;
}
// 省略部分代码
// 很直白的version对比
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
// 回调
observer.mObserver.onChanged((T) mData);
}
复制代码 observer.mActive 在哪被赋值?很多地方。除了一些边界条件的赋值外,一个比较正式的赋值,ObserverWrapper 中的 void activeStateChanged(boolean newActive) 方法:
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
mActive = newActive;
}
// 此方法最终会调到此方法
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
public boolean isAtLeast(@NonNull State state) {
return compareTo(state) >= 0;
}
复制代码很简单,每次生命周期回调,observer.mActive 都会被赋值,而只有到 Lifecycle 是活动状态是,mActive 才会 true。因此只有在我们的 Activity 为前台时我们的 LiveData 才会被回调。