Android LiveData源码分析:为什么他刷新数据比Handler好,能更节省资源,解决内存泄漏的隐患;

目录

  1. 为什么使用
  2. 是什么
  3. 使用+源码分析

一、为什么使用?

1.1 生命周期感知(避免无效刷新)

Handler 的问题​

假设用 Handler 定时刷新 UI:

java 复制代码
// 在 Activity 中
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        updateUI(); // 更新 UI
        handler.postDelayed(this, 1000); // 每秒刷新一次
    }
}, 1000);

如果用户退出 Activity 时忘记调用 handler.removeCallbacks(),​​后台线程会持续触发 UI 更新​​,导致资源浪费甚至崩溃。

​LiveData 的优化​

LiveData 会感知 Activity/Fragment 的生命周期:

typescript 复制代码
// ViewModel 中
MutableLiveData<String> data = new MutableLiveData<>();

// Activity 中观察数据
data.observe(this, new Observer<String>() {
    @Override
    public void onChanged(String value) {
        updateUI(value); // 只在界面活跃时触发
    }
});
1.2、自动解绑观察者(解决内存泄漏)

​Handler 的内存泄漏风险​

如果 Handler 持有 Activity 的隐式引用:

java 复制代码
// 匿名内部类 Handler 默认持有外部类 Activity 的引用
Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        // 如果 Activity 销毁后收到消息,会导致内存泄漏
    }
};

即使 Activity 销毁,只要 Handler 的消息队列未清空,Activity 就无法被回收。

​LiveData 的自动解绑​

LiveData 通过 LifecycleOwner(如 Activity)绑定观察者:

kotlin 复制代码
data.observe(this, observer); // this 是 LifecycleOwner

当 Activity 销毁时,LiveData ​​自动移除观察者​​,断开与 Activity 的引用链,从根源避免内存泄漏。


二、是什么?

LiveData 是 Android Jetpack 组件中的一种 生命周期感知型数据持有类,专为 Android 设计,用于在 数据变化时 自动通知 处于活跃生命周期状态 的观察者(如 Activity/Fragment)。其核心作用是 解决数据与 UI 的实时同步问题,同时避免内存泄漏和生命周期导致的崩溃

LiveData和lifecycler(状态机)挂钩,这也是为什么他能感知生命周期。

LiveData他既是观察者又是被观察者。

三、使用+源码分析

3.1. 创建 LiveData 对象

kotlin 复制代码
class MyViewModel : ViewModel() {
    // MutableLiveData:可变的 LiveData(用于更新数据)
    private val _counter = MutableLiveData<Int>(0)
    // 对外暴露不可变的 LiveData(防止外部直接修改)
    val counter: LiveData<Int> get() = _counter

    fun increment() {
        _counter.value = (_counter.value ?: 0) + 1
    }
}

3.2. 在 Activity/Fragment 中观察数据

kotlin 复制代码
class MyActivity : AppCompatActivity() {
    private lateinit var viewModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 获取 ViewModel
        viewModel = ViewModelProvider(this).get(MyViewModel::class.java)

        // 观察 LiveData 数据变化
        viewModel.counter.observe(this) { value ->
            // 当 counter 数据变化时,自动触发这里的代码
            textView.text = "计数:$value"
        }

        // 触发数据更新
        button.setOnClickListener {
            viewModel.increment()
        }
    }
}

3.2 我们从observe方法开始看,他是如何解决处理生命周期的问题,以及为什么刷新数据比handler好

java 复制代码
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    assertMainThread("observe");
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        // ignore 一进来,我们就可以看到,如果是销毁状态,直接就返回了。
        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);
}

一进来,我们就可以看到,如果是销毁状态,直接就返回了。啥活都不执行了。减少资源消耗。

我们看看 LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);observer被传递进去了,我们看看什么时候会回调。

java 复制代码
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
    // 1. 获取当前 LifecycleOwner(如 Activity/Fragment)的状态
    Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
    
    // 2. 如果当前状态是 DESTROYED(已销毁),自动移除观察者,避免内存泄漏
    if (currentState == DESTROYED) {
        removeObserver(mObserver); // 关键:自动解绑
        return;
    }

    // 3. 处理生命周期变化时的状态同步
    Lifecycle.State prevState = null;
    while (prevState != currentState) {
        prevState = currentState;
        boolean shouldBeActive = shouldBeActive();
        activeStateChanged(shouldBeActive);
        currentState = mOwner.getLifecycle().getCurrentState();
    }
}

这个方法是生命周期方法,生命周期状态变化自动触发逻辑。

我们会发现DESTROYED是Lifecycle下面的,这也是为什么livedata能监听生命周期的原因。

3.3 当我们调用修改数据的时候,他是如何分发过去的?

有两种

ini 复制代码
 _counter.value = (_counter.value ?: 0) + 1
_counter.postValue(1)

(1)我们看看第一种:text

java 复制代码
public class MutableLiveData<T> extends LiveData<T> {

    /**
     * Creates a MutableLiveData initialized with the given {@code value}.
     *
     * @param value initial value
     */
    public MutableLiveData(T value) {
        super(value);
    }

    /**
     * Creates a MutableLiveData with no value assigned to it.
     */
    public MutableLiveData() {
        super();
    }

    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}
typescript 复制代码
@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

传递的是null

Java 复制代码
void dispatchingValue(@Nullable ObserverWrapper initiator) {
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

走下面的for循环逻辑,给所有的观察者分发数据。

java 复制代码
private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
    //
    // we still first check observer.active to keep it as the entrance for events. So even if
    // the observer moved to an active state, if we've not received that event, we better not
    // notify for a more predictable notification order.
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}

直接进行分发 observer.mObserver.onChanged((T) mData);

kotlin 复制代码
fun interface Observer<T> {

    /**
     * Called when the data is changed is changed to [value].
     */
    fun onChanged(value: T)
}

(2)我们看看第二种:postValue postvalue,是子线程来发送数据,但是为什么主线程可以收到消息呢,还可以进行UI操作

ini 复制代码
protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

这个一定会 ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);通过handler切换到主线程。我们先看看这个runnable,里面修改了数据

java 复制代码
private final Runnable mPostValueRunnable = new Runnable() {
    @SuppressWarnings("unchecked")
    @Override
    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        setValue((T) newValue);
    }
};
java 复制代码
@Override
public void postToMainThread(@NonNull Runnable runnable) {
    if (mMainHandler == null) {
        synchronized (mLock) {
            if (mMainHandler == null) {
                mMainHandler = createAsync(Looper.getMainLooper());
            }
        }
    }
    //noinspection ConstantConditions
    mMainHandler.post(runnable);
}

3.4 数据黏性是什么?

LiveData 的 数据黏性 指当新观察者注册时,自动收到最后一次设置的数据

比如:

java 复制代码
liveData.value = "A"
liveData.observe(owner) { value -> 
    println(value) // 立即打印 "A"
}

也就是在注册观察者之前,发送了数据,但还是能收到。

LiveData 内部通过 mData 字段存储当前数据,并通过 mVersion 记录数据版本号。

当调用 observe() 注册观察者时,LiveData 会立即检查是否需要分发当前数据:

不为null,就是黏性数据,立马分发

分发前会检测版本号,如果已经处理过了,就不用处理了。

相关推荐
双桥wow23 分钟前
Android Framework开机动画开发
android
yueqc15 小时前
Kotlin 协程 Flow 操作符总结
kotlin·协程·flow
fanged7 小时前
天马G前端的使用
android·游戏
molong93111 小时前
Kotlin 内联函数、高阶函数、扩展函数
android·开发语言·kotlin
叶辞树13 小时前
Android framework调试和AMS等服务调试
android
慕伏白14 小时前
【慕伏白】Android Studio 无线调试配置
android·ide·android studio
低调小一15 小时前
Kuikly 小白拆解系列 · 第1篇|两棵树直调(Kotlin 构建与原生承载)
android·开发语言·kotlin
跟着珅聪学java15 小时前
spring boot 整合 activiti 教程
android·java·spring
川石课堂软件测试17 小时前
全链路Controller压测负载均衡
android·运维·开发语言·python·mysql·adb·负载均衡
2501_9159214317 小时前
iOS 26 电耗监测与优化,耗电问题实战 + 多工具 辅助策略
android·macos·ios·小程序·uni-app·cocoa·iphone