上一篇聊了 Compose Multiplatform,这篇回到 Jetpack 基础设施。Lifecycle、LiveData、ViewModel 是 Android 架构组件的三件套,天天用但底层怎么实现的?理解源码对排查内存泄漏、数据丢失等问题很有帮助。
Lifecycle 的实现原理
核心接口
// LifecycleOwner:拥有生命周期的对象
interface LifecycleOwner {
val lifecycle: Lifecycle
}
// Lifecycle:生命周期状态机
abstract class Lifecycle {
enum class State {
DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED
}
enum class Event {
ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY, ON_ANY
}
abstract fun addObserver(observer: LifecycleEventObserver)
}
ComponentActivity 的实现
// ComponentActivity.java(简化)
public class ComponentActivity extends Activity implements LifecycleOwner {
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 往 Application 报告生命周期
ReportFragment.injectIfNeededIn(this);
}
}
关键在 ReportFragment。这是一个无 UI 的 Fragment,注入到 Activity 中,在它的生命周期回调里同步通知 LifecycleRegistry:
// ReportFragment.java(简化)
public void onActivityCreated(Bundle savedInstanceState) {
dispatch(Lifecycle.Event.ON_CREATE);
}
public void onStart() {
dispatch(Lifecycle.Event.ON_START);
}
public void onResume() {
dispatch(Lifecycle.Event.ON_RESUME);
}
private void dispatch(Lifecycle.Event event) {
Lifecycle lifecycle = ((LifecycleOwner) requireActivity()).getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
}
}
用 Fragment 而不是直接在 Activity 的回调里通知,是因为 Fragment 的生命周期回调和 Activity 是同步的,且不需要重写 Activity 类。
LifecycleRegistry 的状态管理
LifecycleRegistry 维护了一个状态机和观察者列表:
class LifecycleRegistry : Lifecycle() {
private var state: State = INITIALIZED
private val observerMap = FastSafeIterableMap<LifecycleEventObserver, ObserverWithState>()
fun handleLifecycleEvent(event: Event) {
// 根据事件计算新状态
val next = getStateAfter(event)
// 更新状态并通知所有观察者
moveToState(next)
}
private fun forwardPass() {
// 从当前状态遍历到目标状态,依次通知观察者
for (entry in observerMap) {
while (entry.value.state < state) {
// 上升:CREATED → STARTED → RESUMED
entry.value.dispatchEvent(lifecycleOwner, upEvent(entry.value.state))
}
}
}
}
状态转换是有方向的:上升时 CREATED→STARTED→RESUMED,下降时 RESUMED→STARTED→CREATED→DESTROYED。
ViewModel 的实现原理
ViewModelStore
class ViewModelStore {
private val map = HashMap<String, ViewModel>()
fun put(key: String, viewModel: ViewModel) {
map[key] = viewModel
}
fun get(key: String): ViewModel? = map[key]
fun clear() {
for (vm in map.values) {
vm.clear() // 调用 ViewModel.onCleared()
}
map.clear()
}
}
ViewModelStore 就是一个 HashMap,存 ViewModel 实例。
ViewModel 的存取
// ComponentActivity.java
public ViewModelProvider.ViewModelStoreInfo getViewModelStore() {
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
// 关键:在配置变更时保留 ViewModelStore
NonConfigurationInstances nc = (NonConfigurationInstances)
getLastNonConfigurationInstance();
if (nc != null) {
mViewModelStore = (ViewModelStore) nc.viewmodelStore;
}
}
return mViewModelStore;
}
@Override
public final Object onRetainNonConfigurationInstance() {
// 配置变更(如旋转屏幕)时,ViewModelStore 被保存
// Activity 重建后通过 getLastNonConfigurationInstance 取回
return mViewModelStore;
}
这就是 ViewModel 在屏幕旋转后不丢失数据的原理——通过 onRetainNonConfigurationInstance 保存,重建后取回。
ViewModelProvider
class ViewModelProvider(
private val store: ViewModelStore,
private val factory: Factory
) {
fun <T : ViewModel> get(modelClass: Class<T>): T {
val name = modelClass.name
return store.get(name) as? T ?: create(name, modelClass)
}
private fun <T : ViewModel> create(name: String, modelClass: Class<T>): T {
val viewModel = factory.create(modelClass)
store.put(name, viewModel)
return viewModel
}
}
ViewModelProvider 做的事就是:先从 ViewModelStore 取,取不到就创建并存入。
ViewModel 的生命周期
ViewModel 在 Activity 正常销毁时(onDestroy 非 configChange)会被 ViewModelStore.clear() 调用 onCleared()。但在配置变更时不会被销毁。
Fragment 的 ViewModel 类似,但 ViewModelStore 存在 FragmentManager 中。
LiveData 的实现原理
核心结构
class LiveData<T> {
private var mData: T? = null
private val mObservers = SafeIterableMap<Observer<T>, ObserverWrapper>()
fun observe(owner: LifecycleOwner, observer: Observer<T>) {
val wrapper = LifecycleBoundObserver(owner, observer)
mObservers.putIfAbsent(observer, wrapper)
owner.lifecycle.addObserver(wrapper)
}
fun setValue(value: T) {
mData = value
dispatchingValue(null) // 通知所有活跃观察者
}
fun postValue(value: T) {
// 切到主线程再 setValue
mainHandler.post { setValue(value) }
}
}
LifecycleBoundObserver
inner class LifecycleBoundObserver(
private val owner: LifecycleOwner,
private val observer: Observer<T>
) : LifecycleEventObserver {
var active = false
override fun onStateChanged(source: LifecycleOwner, event: Event) {
val newActive = owner.lifecycle.currentState.isAtLeast(STARTED)
if (newActive != active) {
active = newActive
if (active) {
dispatchingValue(this) // 变活跃时发送最新值
}
}
if (owner.lifecycle.currentState == DESTROYED) {
removeObserver(observer) // 自动清理,防止泄漏
}
}
}
LiveData 的两个核心行为都在这里:
只在活跃状态(STARTED 以上)才通知:避免后台时无意义的数据更新
DESTROYED 时自动移除观察者:不用手动 unregister,不会内存泄漏
版本号防粘性
LiveData 会在观察者变活跃时发送最新值,这就是"粘性"行为。用一个版本号控制:
private var mVersion = 0 // 数据版本
private var mLastVersion = -1 // 观察者上次处理的版本
fun setValue(value: T) {
mVersion++
mData = value
dispatchingValue(null)
}
fun considerNotify(wrapper: ObserverWrapper) {
if (mLastVersion >= mVersion) {
return // 已处理过,不重复通知
}
mLastVersion = mVersion
observer.onChanged(mData)
}
这就是为什么新注册的观察者会收到上次设置的值——mVersion 大于 mLastVersion,会触发一次通知。
常见问题排查
ViewModel 内存泄漏
class MyViewModel : ViewModel() {
private var callback: SomeCallback? = null
fun setCallback(cb: SomeCallback) {
callback = cb // 危险!如果 cb 持有 Activity 引用就泄漏了
}
override fun onCleared() {
callback = null // 必须清理
}
}
LiveData 数据丢失
// 后台 postValue 时如果连续调用多次,只有最后一次生效
liveData.postValue(1)
liveData.postValue(2) // 1 会被丢弃
因为 postValue 只是把任务 post 到主线程,如果主线程还没执行就再次 post,会覆盖。
小结
Lifecycle 用 ReportFragment 桥接 Activity 生命周期,LifecycleRegistry 管理状态机和观察者分发。ViewModel 通过 onRetainNonConfigurationInstance 在配置变更时存活。LiveData 通过 LifecycleBoundObserver 实现活跃感知和自动清理。理解这些原理,排查 ViewModel 泄漏、LiveData 粘性事件等问题就有方向了。
下一篇聊聊 Android 代码质量保障工具链。