目录
- 为什么使用
- 是什么
- 使用+源码分析
一、为什么使用?
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,就是黏性数据,立马分发

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