一、LiveData:生命周期感知的数据持有者 LiveData 是一个可被观察的数据容器类,区别于传统 Observable,它会自动感知观察者(LifecycleOwner)的生命周期状态。具体表现为:当观察者的生命周期处于 STARTED 或 RESUMED 时,LiveData 才向其推送数据更新;当观察者的生命周期变为 DESTROYED 时,订阅关系自动移除。这从根本上杜绝了”Activity 已销毁、回调仍更新 UI”这类经典的 IllegalStateException 和内存泄漏问题。
LiveData 的架构定位很明确——它是 ViewModel 和 UI 之间的数据桥梁:
┌──────────┐ ┌───────────┐ ┌──────────┐ │ Repository│ ───► │ ViewModel │ ───► │ UI │ │ (Data) │ │ (LiveData)│ │(Observer)│ └──────────┘ └───────────┘ └──────────┘ │ 生命周期感知 - 自动订阅/取消 - 只在活跃状态下更新 - 粘性事件
LiveData 有两个常用变体:MutableLiveData 提供了 postValue()(子线程安全)和 setValue()(主线程)用于更新数据;MediatorLiveData 可同时观察多个 LiveData 源,并在任一源变化时进行合并处理,适合多数据源聚合场景。
1.1 LiveData 类图 ┌─────────────────────────┐ │ LiveData<T> │ (抽象类) │ -mObservers: SafeIterableMap │ │ -mVersion: int │ │ -mData: T │ │ +observe(owner, observer)│ │ +observeForever(observer)│ │ +removeObserver(observer)│ │ #setValue(value) │ │ #postValue(value) │ │ #onActive() │ │ #onInactive() │ └──────────┬──────────────┘ │ extends ┌──────┴──────────────────┐ │ MutableLiveData<T> │ │ +setValue(value) │ (public) │ +postValue(value) │ (public) └─────────────────────────┘ │ extends ┌──────┴──────────────────┐ │ MediatorLiveData<T> │ │ +addSource(source, fn) │ │ +removeSource(source) │ └─────────────────────────┘
二、源码解析:订阅如何管理 2.1 observe() 的内部流程 LiveData 的 observe() 方法内部创建了一个 LifecycleBoundObserver,它同时实现了 LifecycleEventObserver 和 ObserverWrapper。当调用 observe(owner, observer) 时,这个包装器被传给 LifecycleRegistry.addObserver(),从而让 Observer 与 LifecycleOwner 的状态同步。
源码核心逻辑(/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java):
observe(LifecycleOwner owner, Observer<T> observer) -> new LifecycleBoundObserver(owner, observer) -> owner.getLifecycle().addObserver(wrapper)
当 LifecycleOwner 状态变为 DESTROYED 时,LifecycleRegistry 调用 onStateChanged(DESTROYED),LifecycleBoundObserver 随即从 LiveData 的观察者列表中移除自身,完成自动取消订阅。
2.2 observe() 完整源码分析 @MainThread public void observe (@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) { assertMainThread("observe" ); if (owner.getLifecycle().getCurrentState() == DESTROYED) { return ; } LifecycleBoundObserver wrapper = new LifecycleBoundObserver (owner, observer); 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 ; } owner.getLifecycle().addObserver(wrapper); }
2.3 LifecycleBoundObserver 的实现 class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver { @NonNull final LifecycleOwner mOwner; LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) { super (observer); mOwner = owner; } @Override boolean shouldBeActive () { return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); } @Override public void onStateChanged (@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) { Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState(); if (currentState == DESTROYED) { removeObserver(mObserver); return ; } Lifecycle.State prevState = null ; while (prevState != currentState) { prevState = currentState; activeStateChanged(shouldBeActive()); currentState = mOwner.getLifecycle().getCurrentState(); } } @Override boolean isAttachedTo (LifecycleOwner owner) { return mOwner == owner; } @Override void detachObserver () { mOwner.getLifecycle().removeObserver(this ); } }
2.4 ObserverWrapper —— 版本号机制 private abstract class ObserverWrapper { final Observer<? super T> mObserver; boolean mActive; int mLastVersion = START_VERSION; ObserverWrapper(Observer<? super T> observer) { mObserver = observer; } abstract boolean shouldBeActive () ; boolean isAttachedTo (LifecycleOwner owner) { return false ; } void detachObserver () {} void activeStateChanged (boolean newActive) { if (newActive == mActive) { return ; } mActive = newActive; changeActiveCounter(mActive ? 1 : -1 ); if (mActive) { dispatchingValue(this ); } } }
2.5 considerNotify() 方法 considerNotify() 方法在分发数据前调用 shouldBeActive() 检查观察者生命周期,只有处于 STARTED 及以上状态才会真正调用 observer.onChanged()。这就是 LiveData 不会向已停止的 Activity 推送更新的根本机制。
private void considerNotify (ObserverWrapper observer) { if (!observer.mActive) { return ; } if (!observer.shouldBeActive()) { observer.activeStateChanged(false ); return ; } if (observer.mLastVersion >= mVersion) { return ; } observer.mLastVersion = mVersion; observer.mObserver.onChanged((T) mData); }
2.6 dispatchingValue —— 数据分发核心 @SuppressWarnings("WeakerAccess") void dispatchingValue (@Nullable ObserverWrapper initiator) { if (mDispatchingValue) { mDispatchInvalidated = true ; return ; } mDispatchingValue = true ; do { mDispatchInvalidated = false ; if (initiator != null ) { considerNotify(initiator); initiator = null ; } else { for (Map.Entry<Observer<? super T>, ObserverWrapper> entry : mObservers.iteratorWithAdditions()) { considerNotify(entry.getValue()); if (mDispatchInvalidated) { break ; } } } } while (mDispatchInvalidated); mDispatchingValue = false ; }
2.7 setValue vs postValue 源码对比 @MainThread protected void setValue (T value) { assertMainThread("setValue" ); mVersion++; mData = value; dispatchingValue(null ); } protected void postValue (T value) { boolean postTask; synchronized (mDataLock) { postTask = mPendingData == NOT_SET; mPendingData = value; } if (!postTask) { return ; } ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable); } private final Runnable mPostValueRunnable = new Runnable () { @SuppressWarnings("unchecked") @Override public void run () { Object newValue; synchronized (mDataLock) { newValue = mPendingData; mPendingData = NOT_SET; } setValue((T) newValue); } };
关键设计点:
setValue() 必须主线程,同步分发。
postValue() 最终调用 setValue(),但通过主线程消息队列调度。
postValue() 在 Runnable 未执行时多次调用,只有最后一次的值生效(前值被覆盖)。
版本号 mVersion 只在 setValue() 中递增,保证每次主线程更新都有一个唯一版本。
LiveData 提供了 Transformations.map() 和 Transformations.switchMap() 两个工具,类似于 RxJava 的 map 和 flatMap:
val userId: LiveData<Int > = MutableLiveData(1 )val userName: LiveData<String> = Transformations.map(userId) { id -> "User_$id " } val user: LiveData<User> = Transformations.switchMap(userId) { id -> repository.getUserById(id) }
@MainThread public static <X, Y> LiveData<Y> map ( @NonNull LiveData<X> source, @NonNull final Function<X, Y> mapFunction) { final MediatorLiveData<Y> result = new MediatorLiveData <>(); result.addSource(source, new Observer <X>() { @Override public void onChanged (@Nullable X x) { result.setValue(mapFunction.apply(x)); } }); return result; }
@MainThread public static <X, Y> LiveData<Y> switchMap ( @NonNull LiveData<X> source, @NonNull final Function<X, LiveData<Y>> switchMapFunction) { final MediatorLiveData<Y> result = new MediatorLiveData <>(); result.addSource(source, new Observer <X>() { LiveData<Y> mSource; @Override public void onChanged (@Nullable X x) { LiveData<Y> newLiveData = switchMapFunction.apply(x); if (mSource == newLiveData) { return ; } if (mSource != null ) { result.removeSource(mSource); } mSource = newLiveData; if (mSource != null ) { result.addSource(mSource, new Observer <Y>() { @Override public void onChanged (@Nullable Y y) { result.setValue(y); } }); } } }); return result; }
switchMap 的典型使用场景:用户选择了一个 ID,根据 ID 从数据库或网络获取对应的详情数据。当用户快速切换 ID 时,switchMap 会自动取消旧请求的结果监听,只关注最新 ID 的结果——这个行为与 RxJava 的 switchMap 完全一致。
虽然 LiveData 没有内置此方法,但它是常用的扩展:
fun <T> LiveData<T> .distinctUntilChanged () : LiveData<T> { val output = MediatorLiveData<T>() var firstTime = true output.addSource(this ) { value -> val previous = output.value if (firstTime || value != previous) { firstTime = false output.value = value } } return output }
MediatorLiveData 是 LiveData 的子类,可以同时观察多个 LiveData 源。它是 Transformations.map() 和 switchMap() 的底层实现基础。
public class MediatorLiveData <T> extends MutableLiveData <T> { private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap <>(); @MainThread public <S> void addSource (@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) { Source<S> e = new Source <>(source, onChanged); Source<?> existing = mSources.putIfAbsent(source, e); if (existing != null ) { return ; } if (hasActiveObservers()) { e.plug(); } } @MainThread public <S> void removeSource (@NonNull LiveData<S> source) { Source<?> sourceToRemove = mSources.remove(source); if (sourceToRemove != null ) { sourceToRemove.unplug(); } } @Override protected void onActive () { for (Map.Entry<LiveData<?>, Source<?>> entry : mSources) { entry.getValue().plug(); } } @Override protected void onInactive () { for (Map.Entry<LiveData<?>, Source<?>> entry : mSources) { entry.getValue().unplug(); } } private static class Source <V> implements Observer <V> { final LiveData<V> mLiveData; final Observer<? super V> mObserver; int mVersion = START_VERSION; Source(LiveData<V> liveData, Observer<? super V> observer) { mLiveData = liveData; mObserver = observer; } void plug () { mLiveData.observeForever(this ); } void unplug () { mLiveData.removeObserver(this ); } @Override public void onChanged (@Nullable V v) { if (mVersion != mLiveData.getVersion()) { mVersion = mLiveData.getVersion(); mObserver.onChanged(v); } } } }
关键设计:
MediatorLiveData 使用 observeForever() 监听源 LiveData(不需要 LifecycleOwner)。
通过 onActive() / onInactive() 控制对源 LiveData 的监听——只有当 MediatorLiveData 自身有活跃观察者时才监听源,避免无用计算。
每个源封装为一个 Source 对象,通过版本号避免重复通知。
class OrderSummaryViewModel : ViewModel () { val price: LiveData<Double > = repository.getPrice() val quantity: LiveData<Int > = MutableLiveData(1 ) val discount: LiveData<Double > = MutableLiveData(0.0 ) val total: MediatorLiveData<Double > = MediatorLiveData<Double >().apply { var lastPrice = 0.0 var lastQuantity = 1 var lastDiscount = 0.0 fun updateTotal () { value = lastPrice * lastQuantity * (1 - lastDiscount) } addSource(price) { p -> lastPrice = p updateTotal() } addSource(quantity) { q -> lastQuantity = q updateTotal() } addSource(discount) { d -> lastDiscount = d updateTotal() } } }
五、LiveData 的粘性事件问题与解决方案 5.1 什么是粘性事件(Sticky Event) LiveData 默认是粘性的——当新的 Observer 注册时,会立即收到 LiveData 中最后一次设置的值。这是设计特性而非 bug:
val data = MutableLiveData<String>()data .value = "Hello" data .observe(lifecycleOwner) { value -> }
这个特性在多数场景下是优势(如配置变更后新 Activity 立即获取已有数据),但在处理一次性事件 (如导航、Snackbar、Toast)时会成为问题:
class MyViewModel : ViewModel () { val navigateToDetail = MutableLiveData<Event<String>>() fun onItemClick (itemId: String ) { navigateToDetail.value = Event(itemId) } } class MyActivity : AppCompatActivity () { override fun onCreate (savedInstanceState: Bundle ?) { super .onCreate(savedInstanceState) viewModel.navigateToDetail.observe(this ) { event -> } } }
5.2 SingleLiveEvent 方案 class SingleLiveEvent <T > : MutableLiveData <T >() { private val mPending = AtomicBoolean(false ) override fun observe (owner: LifecycleOwner , observer: Observer <in T >) { super .observe(owner) { t -> if (mPending.compareAndSet(true , false )) { observer.onChanged(t) } } } override fun setValue (t: T ?) { mPending.set (true ) super .setValue(t) } override fun postValue (value: T ) { mPending.set (true ) super .postValue(value) } }
5.3 Event 包装器方案 class Event <out T >(private val content: T) { private var hasBeenHandled = false fun getContentIfNotHandled () : T? { return if (hasBeenHandled) { null } else { hasBeenHandled = true content } } fun peekContent () : T = content } class MyViewModel : ViewModel () { val navigateToDetail = MutableLiveData<Event<String>>() fun onItemClick (itemId: String ) { navigateToDetail.value = Event(itemId) } } viewModel.navigateToDetail.observe(this ) { event -> event.getContentIfNotHandled()?.let { itemId -> navigateToDetail(itemId) } }
5.4 Kotlin Channel 方案(推荐) class MyViewModel : ViewModel () { private val _navigationEvents = Channel<NavigationEvent>(Channel.BUFFERED) val navigationEvents = _navigationEvents.receiveAsFlow() fun onItemClick (itemId: String ) { viewModelScope.launch { _navigationEvents.send(NavigationEvent.ToDetail(itemId)) } } } lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.navigationEvents.collect { event -> when (event) { is NavigationEvent.ToDetail -> navigateToDetail(event.itemId) } } } }
Channel 方案的优势:
Channel 天然非粘性,发送的事件只被消费一次
配合 repeatOnLifecycle,生命周期安全
类型安全(使用 sealed class 定义所有事件)
六、LiveData vs Kotlin Flow / StateFlow 6.1 核心对比
特性
LiveData
StateFlow
SharedFlow
生命周期感知
是(自动)
否(需 repeatOnLifecycle)
否
平台
Android 专属
Kotlin 跨平台
Kotlin 跨平台
粘性
是(默认粘性)
是(always holds a value)
可配置(replay)
线程安全
部分(setValue 主线程,postValue 任意)
是(所有操作线程安全)
是
操作符
有限(map, switchMap)
丰富(Flow 全套操作符)
丰富
背压处理
无
有(conflated)
可配置
数据去重
否
是(自动 distinctUntilChanged)
可配置
多观察者
是
是(但每个 collector 独立)
是
6.2 LiveData 与 Flow 的互转 fun <T> LiveData<T> .asFlow () : Flow<T> = callbackFlow { val observer = Observer<T> { value -> trySend(value) } observeForever(observer) awaitClose { removeObserver(observer) } } fun <T> Flow<T> .asLiveData () : LiveData<T> { val liveData = MutableLiveData<T>() return liveData } @JvmOverloads fun <T> Flow<T> .asLiveData ( context: CoroutineContext = EmptyCoroutineContext, timeoutInMs: Long = DEFAULT_TIMEOUT ) : LiveData<T> = liveData(context, timeoutInMs) { collect { value -> emit(value) } }
6.3 选择指南
ViewModel -> UI :LiveData 仍是一个好选择(简单、生命周期安全、与 DataBinding 深度集成)。如果团队熟悉 Flow,也可以使用 StateFlow + repeatOnLifecycle。
Repository -> ViewModel :强烈推荐 Flow。冷流(cold flow)自动管理资源,丰富的操作符(map、filter、combine、catch、retry),不依赖 Android 平台。
数据库观察 :Room 原生支持 Flow 返回类型,配合 Flow 使用体验最好。
一次性事件 :Channel + Flow 优于 LiveData + Event 包装器。
跨平台共享代码 (KMM):只能用 Flow/StateFlow(LiveData 是 Android 专属)。
七、DataBinding 与 LiveData 的集成 DataBinding 与 LiveData 的集成是实现 MVVM 数据驱动 UI 的关键:
<layout > <data > <variable name ="viewModel" type ="com.example.MyViewModel" /> </data > <LinearLayout > <TextView android:text ="@{viewModel.userName}" android:visibility ="@{viewModel.isLoading ? View.GONE : View.VISIBLE}" /> </LinearLayout > </layout >
class MyActivity : AppCompatActivity () { override fun onCreate (savedInstanceState: Bundle ?) { super .onCreate(savedInstanceState) val binding: ActivityMainBinding = DataBindingUtil.setContentView(this , R.layout.activity_main) binding.lifecycleOwner = this binding.viewModel = viewModel } }
DataBinding + LiveData 的工作流程:
DataBinding 在编译期生成 LiveDataListener,它实现了 Observer 接口。
当 View 绑定了一个 LiveData 表达式时,DataBinding 自动调用 liveData.observe(lifecycleOwner, observer)。
lifecycleOwner 控制 Observer 的活跃状态。
当 LiveData 值变化且 Observer 活跃时,DataBinding 自动更新 View。
面试常考问题 Q1: LiveData 与 Kotlin Flow / StateFlow 的对比与选择?
A: LiveData 生命周期感知能力强,自动处理订阅/取消,与 Android UI 天然绑定——但它是 Android 平台专属,不适用于纯 Kotlin 模块。StateFlow 是 Kotlin 协程生态的一部分,跨平台可用,配合 repeatOnLifecycle 也能实现安全的 UI 数据收集。选择建议:ViewModel 与 UI 之间的通信仍可使用 LiveData,Repository/DataSource 层的数据流使用 Flow,通过 asLiveData() 扩展函数可无缝转换。
关键区别:
LiveData 通过 LifecycleBoundObserver 自动管理订阅生命周期,Observer 在 DESTROYED 时自动移除。
StateFlow 需要通过 repeatOnLifecycle(STARTED) 手动管理生命周期。
StateFlow 自动去重(distinctUntilChanged),LiveData 每次 setValue() 都会通知(即使值相同)。
StateFlow 是热流(hot flow),始终持有最新值;LiveData 也是粘性的,但通过 observeForever 可以观察到所有更新。
StateFlow 有结构化的并发支持(stateIn()),Flow 有丰富的终止操作符(first()、take() 等)。
Q2: postValue 和 setValue 的区别?
A: setValue() 必须在主线程调用,立即同步更新数据并通知观察者。postValue() 可在任意线程调用,它将值加入主线程的消息队列中异步执行(内部通过 ArchTaskExecutor.postToMainThread() 实现)。源码中 postValue 还有一个保护:如果在主线程的 Runnable 尚未执行前多次调用 postValue,只有最后一次的值会被分发,中间值会被覆盖。
源码流程分析:
postValue(value): 1. synchronized(mDataLock) { mPendingData = value; } 2. if (!postTask): 已经有一个 post 任务在排队,直接更新 mPendingData 后返回 3. ArchTaskExecutor.postToMainThread(mPostValueRunnable) mPostValueRunnable.run(): 1. synchronized(mDataLock) { newValue = mPendingData; mPendingData = NOT_SET; } 2. setValue(newValue) // 在主线程调用
这意味着:
如果你连续 3 次调用 postValue("A"), postValue("B"), postValue("C"),Observer 可能只收到 "C"(中间的 “A” 和 “B” 被覆盖)。
setValue 每次调用都会分发,Observer 会依次收到 “A”, “B”, “C”。
postValue 适合子线程更新,setValue 适合主线程更新。
Q3: LiveData 数据倒灌(Sticky Event)是什么?如何解决?
A: LiveData 默认是粘性的——新的观察者注册时会立即收到最后一次发射的数据。这在处理一次性事件(如导航指令、Snackbar)时会导致问题:屏幕旋转后重建的 Activity 会再次收到旧导航事件。
三种解决方案:
SingleLiveEvent:内部用 AtomicBoolean 控制事件只被消费一次。
Event 包装器:Event.getContentIfNotHandled() 返回 null 如果已被消费。
Channel + Flow(推荐):Channel 天然非粘性,配合 repeatOnLifecycle 实现生命周期安全的单次事件消费。
为什么粘性事件是”特性”而非”bug”?在多数场景下,粘性事件是需要的——比如屏幕旋转后,新的 Activity 需要立即获取 ViewModel 中已有的用户信息数据,而无需重新加载。粘性只在处理一次性事件时才成为问题。
Q4: LiveData 的活跃状态判断逻辑是什么?
A: LiveData 判断 Observer 是否”活跃”的核心逻辑在 LifecycleBoundObserver.shouldBeActive() 中:
boolean shouldBeActive () { return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); }
只有 LifecycleOwner 的状态 >= STARTED(即 STARTED 或 RESUMED)时,Observer 才是活跃的。
完整的状态转换:
CREATED -> STARTED(对应 onStart):Observer 变为活跃,activeStateChanged(true) 被调用,立即收到最新数据。
STARTED -> CREATED(对应 onStop):Observer 变为非活跃,activeStateChanged(false) 被调用,停止接收数据。
Lifecycle.DESTROYED:Observer 被自动移除,完全取消订阅。
这意味着:
Activity 在后台(onStop 之后)不会再收到 LiveData 更新,不会触发不必要的 UI 刷新。
Fragment 在 back stack 中(onStop 之后)也不会收到更新。
一旦回到前台(onStart),会立即收到最新的数据,确保 UI 显示的是最新状态。
Q5: MediatorLiveData 与 combine 操作符有什么区别?何时使用?
A: MediatorLiveData 可以手动添加多个源并通过回调自定义合并逻辑。它是命令式的:你显式调用 addSource() 并编写合并逻辑。而 Flow 的 combine 操作符是声明式的。
val result = MediatorLiveData<String>()result.addSource(liveData1) { v1 -> result.value = "$v1 -${liveData2.value} " } result.addSource(liveData2) { v2 -> result.value = "${liveData1.value} -$v2 " } val result: Flow<String> = combine(flow1, flow2) { v1, v2 -> "$v1 -$v2 " }
选择建议:
只有一个或两个源:MediatorLiveData 更简单直接。
三个及以上源:Flow 的 combine 更清晰,不易出错。
需要复杂的数据流处理(如 debounce、throttle、retry):Flow 有丰富的操作符。
需要与 DataBinding 集成:LiveData 是 DataBinding 的原生支持类型。
核心参考 AOSP 路径:
lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java — LiveData 核心实现
lifecycle/livedata-core/src/main/java/androidx/lifecycle/ObserverWrapper.java — Observer 包装器
lifecycle/livedata-core/src/main/java/androidx/lifecycle/Transformations.java — 数据变换
lifecycle/livedata-core/src/main/java/androidx/lifecycle/MediatorLiveData.java — 多源合并
lifecycle/livedata-ktx/src/main/java/androidx/lifecycle/LiveData.kt — Kotlin 扩展
lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/LifecycleRegistry.java — 生命周期管理
databinding/library/src/main/java/android/databinding/DataBindingUtil.java — DataBinding 集成