Administrator
发布于 2026-08-25 / 27 阅读
0
0

系列文章《Android 工程师的 100 篇进阶笔记》第 49 篇:Lifecycle 源码解析:Lifecycle、LiveData 与 ViewModel 底层原理

上一篇聊了 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 的两个核心行为都在这里:

  1. 只在活跃状态(STARTED 以上)才通知:避免后台时无意义的数据更新

  2. 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 代码质量保障工具链。


评论