Android 内存泄漏 -> LiveData如何解决ViewMode和Activity/Fragment之间的内存泄漏

LiveData 是如何解决的?(源码分析)

LiveData 没有直接持有 Activity,而是持有了一个 Observer(观察者),而这个 Observer 被包装在一个 生命周期感知器 中。

核心机制: 当 Activity 变为 DESTROYED 状态时,LiveData 会自动把自己从观察者列表中移除。引用链断裂,Activity 就可以被回收了。

observe 方法:绑定的开始,当你调用 viewModel.liveData.observe(this, observer) 时:

java 复制代码
// LiveData.java
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    // 1. 如果当前页面已经销毁了,直接忽略,不注册
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        return;
    }
    
    // 2. 将 owner (Activity) 和 observer 包装成一个 LifecycleBoundObserver
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    
    // 3. 保存到 map 中
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    
    // 4. 【关键】将这个 wrapper 注册到 Activity 的生命周期中
    // 这样 wrapper 就能收到 onStart, onStop, onDestroy 等回调
    owner.getLifecycle().addObserver(wrapper);
}

LifecycleBoundObserver:核心内部类,实现了 LifecycleEventObserver,它会监听 Activity 的生命周期变化

java 复制代码
// LiveData.java 的内部类
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
    @NonNull final LifecycleOwner mOwner;

    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
        super(observer);
        mOwner = owner;
    }

    @Override
    public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
        // 【核心代码在这里!】
        // 每次生命周期变化都会回调这里
        
        // 1. 自动断开引用机制
        // 如果当前状态是 DESTROYED (Activity 正在销毁)
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            // 调用 removeObserver,把自己从 LiveData 的列表中移`在这里插入代码片`除
            removeObserver(mObserver);
            return;
        }
        
        // 2. 只有在活跃状态 (STARTED/RESUMED) 才发送数据更新
        activeStateChanged(shouldBeActive());
    }
}

3. removeObserver:彻底断开

java 复制代码
// LiveData.java
public void removeObserver(@NonNull final Observer<? super T> observer) {
    ObserverWrapper removed = mObservers.remove(observer);
    if (removed == null) {
        return;
    }
    // 取消监听生命周期,彻底解绑
    removed.detachObserver();
    removed.activeStateChanged(false);
}

总结:LiveData 的高明之处

LiveData 并不是简单地"持有引用然后置空",它引入了 Inversion of Control (控制反转)ViewModel 不认识 ActivityViewModel 里的 LiveData 只是一个数据容器,它不知道谁在观察它。Activity 自己管理自己:Activity 通过 observe 告诉 LiveData:"我有生命周期,我死的时候(DESTROYED),请不要再理我,把我的引用扔掉。"

自动清理:
Activity A (Old) 销毁 -> 触发 LifecycleBoundObserver.onStateChanged -> 检测到 DESTROYED -> removeObserver -> 引用断开,Activity A 被回收。
Activity A (New) 重建 -> 调用 observe -> 注册新的 Observer -> ViewModel 连接到新的 Activity

相关推荐
故事和你9116 分钟前
洛谷-数据结构1-1-线性表1
开发语言·数据结构·c++·算法·leetcode·动态规划·图论
JJay.1 小时前
Android BLE 稳定连接的关键,不是扫描,而是 GATT 操作队列
android·服务器·前端
techdashen1 小时前
Rust项目公开征测:Cargo 构建目录新布局方案
开发语言·后端·rust
一 乐1 小时前
电影院|基于springboot + vue电影院购票管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·电影院购票管理管理系统
星空椰1 小时前
JavaScript 进阶基础:函数、作用域与常用技巧总结
开发语言·前端·javascript
恼书:-(空寄1 小时前
JVM GC 日志分析 + 常见 GC 场景 + 实战参数调优
java·jvm
消失的旧时光-19431 小时前
Spring Boot 实战(五):接口工程化升级(统一返回 + 异常处理 + 错误码体系 + 异常流转机制)
java·spring boot·后端·解耦
忒可君1 小时前
C# winform 自制分页功能
android·开发语言·c#
summerkissyou19871 小时前
Android-线程安全-volatile
android·线程
Rust研习社2 小时前
Rust 智能指针 Cell 与 RefCell 的内部可变性
开发语言·后端·rust