Jetpck 才是真的豪华全家桶
引言
- LiveData 是一种可观察的数据存储器类。
- LiveData 具有生命周期感知能力(遵循Activity、Fragment 或 Service等生命周期)。
- LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
整体预览
1. 使用说明
1.1 特点
- 确保界面符合数据状态
- LiveData 遵循观察者模式。当底层数据发生变化时,LiveData 会通对象。
- 不会发生内存泄漏
- 观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理。
- 不会因 Activity 停止而导致崩溃
- 如果观察者的生命周期处于非活跃状态(如返回栈中的 Activity),则它不会接收任何 LiveData 事件。
- 不再需要手动处理生命周期
- 界面组件只是观察相关数据,不会停止或恢复观察。LiveData 将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。
- 数据始终保持最新状态
- 如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。
- 适当的配置更改
- 如果由于配置更改(如设备旋转)而重新创建了 Activity 或 Fragment,它会立即接收最新的可用数据。
- 共享资源
- 可以使用单例模式扩展
LiveData
对象以封装系统服务,以便在应用中共享它们。
- 可以使用单例模式扩展
1.2 创建
参考下面【代码展示】: LiveData 对象通常存储在 ViewModel 对象中,并可通过 getter 方法进行访问。
1.3 观察
参考下面【代码展示】: 应用组件的 onCreate() 方法是开始观察 LiveData 对象的正确着手点。
1.4 更新
参考下面【代码展示】: MutableLiveData是LiveData的子类,公开 setValue(T) 和 postValue(T) 方法,修改存储在 LiveData 对象中的值。
【代码展示】:基础语法
// 1.2 创建
/**
* LiveData 对象存储在 ViewModel 对象中
* ps-1:避免 Activity 和 Fragment 过于庞大。现在,这些界面控制器负责显示数据,但不负责存储数据状态。
* ps-2:将 LiveData 实例与特定的 Activity 或 Fragment 实例分离开,并使 LiveData 对象在配置更改后继续存在。
*/
class LiveModel : ViewModel() {
val name: MutableLiveData by lazy {
MutableLiveData()
}
val allLifeName: MutableLiveData by lazy {
MutableLiveData()
}
}
// 1.3 观察 & 1.4 更新
private const val TAG = "KJYR_LiveDataActivity"
class LiveDataActivity : AppCompatActivity() {
//LiveModel定义
lateinit var model: LiveModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_live_data)
Log.d(TAG, "onCreate() called ")
model = LiveModel()
//基础使用:onCreate() 方法是开始观察 LiveData 对象:
//ps-1:确保系统不会从 Activity 或 Fragment 的 onResume() 方法进行冗余调用。
//ps-2:确保 Activity 或 Fragment 变为活跃状态后具有可以立即显示的数据。
// 1.3 观察:创建可定义 onChanged() 方法的 Observer 对象
val observer: Observer = Observer { name ->
Log.d(TAG, "KJYR onChanged() : name = $name")
}
//1.3 观察: 使用 observe() 方法将 Observer 对象附加到 LiveData 对象
// 1.3 观察:第一个参数是:LifecycleOwner(因为Activity实现了它,直接用即可)
model.name.observe(this, observer)
// 1.4 更新 : 非活跃状态不更新
model.name.value = "onCreate"
//1.3 观察:持久监听:observeForever
model.allLifeName.observeForever { name ->
Log.d(TAG, "KJYR onChanged() : all life name = $name")
}
model.allLifeName.value = "onCreate"
}
override fun onStart() {
super.onStart()
Log.d(TAG, "onStart() called")
// 1.4 更新 : 如果在工作器线程中执行代码,可以改用 postValue(T) 方法来更新 LiveData 对象。
// 1.4 更新 : 活跃状态更新
model.name.value = "onStart"
}
}
2. 高级用法
2.1 扩展
下面示例:名字上报(触发器->管理器->接收器)
核心:LiveData 活跃状态回调 onActive()
,非活跃状态回调onInactive()
。
/**
* 名字上报触发器
*/
class NameReportManager {
private var listener: NameListener? = null
private val handler = Handler(Looper.getMainLooper())
private var count = 0;
private val runnable: Runnable = object : Runnable {
override fun run() {
count++
listener?.onNameReport("KJYR send : $count")
handler.postDelayed(this, 1000)
}
}
fun register(listener: NameListener) {
this.listener = listener
handler.postDelayed(runnable, 1000)
}
fun unregister(listener: NameListener) {
this.listener = null
handler.removeCallbacks(runnable)
}
interface NameListener {
fun onNameReport(name: String)
}
}
/**
* 名字上报管理器(活跃状态有效)
*/
class NameLiveData : LiveData() {
private val nameReport = NameReportManager()
private val listener: NameListener = object : NameListener {
override fun onNameReport(name: String) {
value = "KJYR receive $name"
}
}
//设置监听
override fun onActive() {
nameReport.register(listener)
}
//移除监听
override fun onInactive() {
nameReport.unregister(listener)
}
companion object {
private lateinit var sInstance: NameLiveData
fun get(): NameLiveData {
sInstance = if (::sInstance.isInitialized) sInstance else NameLiveData()
return sInstance
}
}
}
//名字上报接收器
class LiveDataActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_live_data)
Log.d(TAG, "onCreate() called ")
//扩展实现:名字上报接收器
NameLiveData.get().observe(this, {name ->
Log.d(TAG, "KJYR: Notify = $name")
})
}
}
2.2 转换
下面示例:获取名字长度(String -> Int)
核心:Lifecycle 软件包会提供 Transformations 类,Transformations 中通过 MediatorLiveData 来实现。当然可以使用 MediatorLiveData 实现更多的类型转换。
class LiveModel : ViewModel() {
val name: MutableLiveData by lazy {
MutableLiveData()
}
//map
val length: LiveData = Transformations.map(name) { input ->
input.length
}
//switch:switchMap() 的函数必须返回 LiveData 对象
val nameLength: LiveData = Transformations.switchMap(name) { input ->
MutableLiveData(input.length)
}
}
class LiveDataActivity : AppCompatActivity() {
//LiveModel定义
lateinit var model: LiveModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_live_data)
Log.d(TAG, "onCreate() called ")
model = LiveModel()
//转换:map
model.length.observe(this) { length ->
Log.d(TAG, "KJYR map: length = $length")
}
//转换:switchMap
model.nameLength.observe(this) { nameLength ->
Log.d(TAG, "KJYR switchMap: nameLength = $nameLength")
}
}
override fun onStart() {
super.onStart()
Log.d(TAG, "onStart() called")
model.name.value = "onStart"
}
}
2.3 合并
下面示例:名字或者长度 改变 更新混合源信息(multiInfo
)
核心:MediatorLiveData 是 LiveData 的子类,允许合并多个 LiveData 源。只要任何原始的 LiveData 源对象发生更改,就会触发 MediatorLiveData 对象的观察者。
class LiveModel : ViewModel() {
val name: MutableLiveData by lazy {
MutableLiveData()
}
//map
val length: LiveData = Transformations.map(name) { input ->
input.length
}
//MediatorLiveData
val multiInfo = MediatorLiveData()
fun setMultiInfo() {
multiInfo.addSource(name) { name ->
multiInfo.value = "name = $name"
}
multiInfo.addSource(length) { length ->
multiInfo.value = "value = $length"
}
}
}
class LiveDataActivity : AppCompatActivity() {
//LiveModel定义
lateinit var model: LiveModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_live_data)
Log.d(TAG, "onCreate() called ")
model = LiveModel()
//合并多源:MediatorLiveData
model.multiInfo.observe(this) { info ->
Log.d(TAG, "KJYR MediatorLiveData: info = $info")
}
model.setMultiInfo()
}
override fun onStart() {
super.onStart()
Log.d(TAG, "onStart() called")
model.name.value = "onStart"
}
}
3. 原理分析
3.1 数据流向
3.1.1 数据流向 - 整体概览
3.1.2 数据流向 - 核心类关系
3.1.3 数据流向 - 订阅 observe
【源码分析】- LiveData.observe()
/**
* 注册监听:活跃状态
*/
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {
assertMainThread("observe"); //注释:线程保证,主线程注册
//注释:当前组件(比如activity)的LifecycleOwner是DESTROYED状态时,直接忽略
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//注释:组装包装类(实现了LifecycleObserver接口),核心参数:LifecycleOwner + Observer
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//注释:链表(mObservers)添加键值对,存在:直接返回,不存在:添加,返回null
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//注释:如果当前wrapper已经存在,且关联的不是当前owner,抛异常(因为观察者只能与一个owner绑定)
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
//注释:如果当前wrapper已经存在,并且关联的就是当前owner,则不需要额外注册,直接返回即可
if (existing != null) {
return;
}
//注释:通过当前owner,获得Lifecycle,添加注册
owner.getLifecycle().addObserver(wrapper);
}
3.1.4 数据流向 - 订阅 observeForever
【源码分析】- LiveData.observeForever()
/**
* 注册监听:任何状态
*/
@MainThread
public void observeForever(@NonNull Observer super T> observer) {
assertMainThread("observeForever"); //注释:线程保证,主线程注册
//注释:AlwaysActiveObserver 重写方法 shouldBeActive(), 忽略状态判断,任何状态都回调改变
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//注释:如果当前wrapper已经存在,并且是LifecycleBoundObserver(生命周期约束组件),抛异常(与目标不符)
if (existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
//注释:已经存在,且类型正常,则直接返回,不需要进行
if (existing != null) {
return;
}
//注释:因为是全状态可监听回调,所以不需要LifecycleOwner参与,直接调用触发状态设置即可,永久有效,除非主动移除
wrapper.activeStateChanged(true);
}
3.1.5 数据流向 - 订阅 activeStateChanged
(1)【源码分析】- LiveData.LifecycleBoundObserver
//注释:受LifecycleOwner约束的监听器,UI常用组件
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer super T> observer) {
super(observer);
mOwner = owner;
}
//注释:LifecycleOwner是 STARTED 或者 RESUMED 状态时,才是活跃状态
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
//注释:监听 lifecycle 回调
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
//注释: 收到 DESTROYED 状态会自动解除跟 owner 的绑定
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
//注释:while的意义(在活跃状态调用中,mOwner生命周期状态存在变更,及时处理)
while (prevState != currentState) {
prevState = currentState;
activeStateChanged(shouldBeActive()); //注释:活跃状态变更调用
currentState = mOwner.getLifecycle().getCurrentState();
}
}
//注释:是否与当前onwer相同
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
(2)【源码分析】- LiveData.AlwaysActiveObserver
//不依赖LifecycleOwner的活跃监听
private class AlwaysActiveObserver extends ObserverWrapper {
AlwaysActiveObserver(Observer super T> observer) {
super(observer);
}
@Override
boolean shouldBeActive() {
return true; //注释:始终为活跃状态,专门为observeForever而生
}
}
(3)【源码分析】- LiveData.ObserverWrapper
private abstract class ObserverWrapper {
final Observer super T> mObserver; //注释:当前监听器
boolean mActive; //注释:是否为活跃状态
int mLastVersion = START_VERSION; //注释: 版本号(ObserverWrapper)
ObserverWrapper(Observer super T> observer) {
mObserver = observer;
}
//注释: 是否为活跃状态,为了实现多态子类(受生命周期约束的,不受生命周期约束的)
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
void detachObserver() {
}
//注释:活跃状态变更
void activeStateChanged(boolean newActive) {
//注释: 活跃状态未变更,则不处理
if (newActive == mActive) {
return;
}
//注释:当前活跃状态更新
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
//注释:存在活跃状态,则进行值的更新分发
if (mActive) {
dispatchingValue(this);
}
}
}
(4)【源码分析】- LiveData.changeActiveCounter()
//注释:更改活动计数器
@MainThread
void changeActiveCounter(int change) {
int previousActiveCount = mActiveCount;
mActiveCount += change;
if (mChangingActiveState) { //注释:活动计数器 已经在分发更新,则返回
return;
}
mChangingActiveState = true; //注释:活动计数器 分发标记 设置
try {
//注释:while循环的意义(在活跃状态的通知过程中,活跃数量存在变更时,
//则再次进行活跃状态通知的检测与更新,防止状态遗漏)
while (previousActiveCount != mActiveCount) {
//注释:活动监听器 0 -> 1, 需要回调活跃通知
boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0;
//注释:活动监听器 1 -> 0, 需要回调非活跃通知
boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0;
previousActiveCount = mActiveCount;
if (needToCallActive) {
onActive(); //注释:活跃通知
} else if (needToCallInactive) {
onInactive(); //注释:非活跃通知
}
}
} finally {
mChangingActiveState = false; //注释:活动计数器 分发标记 清除
}
}
(5)【源码分析】- LiveData.dispatchingValue()
/**
* 分发更新
*/
@SuppressWarnings("WeakerAccess") /* synthetic access */
void dispatchingValue(@Nullable ObserverWrapper initiator) {
//注释:正在分发过程中,则标记当前分发失效(mDispatchInvalidated)
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true; //注释:分发标识 开始
do {
mDispatchInvalidated = false; //注释:当前分发失效清空
if (initiator != null) {
//注释:因为这个分支是 生命周期变更 触发(会有同状态忽略处理的保护,以及版本保护),
//不需要参与分发实效的重试,通知完成糊,直接清空标记(initiator = null)
//注释:ObserverWrapper.activeStateChanged 传入 this(ObserverWrapper)
considerNotify(initiator); //注释:考虑通知
initiator = null;
} else {
//注释:setValue 出入 null, 通知 active状态的 mObservers
for (Iterator, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue()); //注释:考虑通知
//注释:在遍历过程中,如果遇到值更新(当前分发实效),则立马退出当前分发,
//重新从头开始遍历分发(也就是走到:while 处,再执行 do 中逻辑)
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false; //注释:分发标识 结束
}
(6)【源码分析】- LiveData.considerNotify()
/**
* 判断通知
*/
@SuppressWarnings("unchecked")
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) { //注释:判断当前已保存状态为:非活跃状态,则不处理
return;
}
//注释:获取当前最新状态,并检查,如果是非活跃状态,则更新以保存的状态,不进行后续处理。
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//注释:版本判断,只有值变更,才会进行
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion; //注释:更新版本
//注释:回调mObserver的onChanged方法 结束
observer.mObserver.onChanged((T) mData);
}
3.1.6 数据流向 - 更新分发 setValue
【源码分析】- LiveData.setValue() / postValue()
//注释:postValue()的异步更新
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) { //注释:线程安全更新
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue); //注释:最终回到setValue()方法
}
};
//注释:子线程更新值(通过Handler分发到主线程)
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
//注释:主线程更新值
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
//注释:每次更新数据,版本都会自增,默认值是 -1。
mVersion++;
mData = value;
dispatchingValue(null);
}
3.2 转换原理
3.2.1 转换原理 - Transformations.map
创建 MediatorLiveData(MutableLiveData 的子类),通过 addSource()
方法将目标 LiveData 与 高阶函数创建的 Observer 进行关联,最后将转换后的值更新到 MediatorLiveData,并将 MediatorLiveData 返回,从而得到新的 LiveData,且与目标 LiveData 产生自关联。
【源码分析】- Transformations.map()
public static LiveData map(
@NonNull LiveData source,
@NonNull final Function mapFunction) {
final MediatorLiveData result = new MediatorLiveData<>();
//注释:将传入的高阶函数,返回内容,设置到 MediatorLiveData
result.addSource(source, new Observer() {
@Override
public void onChanged(@Nullable X x) {
//注释:入参方法计算返回
result.setValue(mapFunction.apply(x));
}
});
return result;
}
3.2.2 转换原理 - Transformations.switchMap
与 map()
一样,只是多套了一层娃,达到高阶函数的类型匹配。
【源码分析】- Transformations.switchMap()
public static LiveData switchMap(
@NonNull LiveData source,
@NonNull final Function> switchMapFunction) {
final MediatorLiveData result = new MediatorLiveData<>();
result.addSource(source, new Observer() {
LiveData mSource;
@Override
public void onChanged(@Nullable X x) {
//注释:入参方法计算返回
LiveData newLiveData = switchMapFunction.apply(x);
if (mSource == newLiveData) {
return;
}
if (mSource != null) {
result.removeSource(mSource);
}
mSource = newLiveData;
//返回的LiveData, 同理再次套娃(将监听器与mSource关联)
if (mSource != null) {
result.addSource(mSource, new Observer() {
@Override
public void onChanged(@Nullable Y y) {
result.setValue(y);
}
});
}
}
});
return result;
}
3.2.3 转换原理 - Transformations.distinctUntilChanged
原理相似,只是实现了具体业务场景:在更改之前保持不变。
3.2.4 转换原理 - MediatorLiveData
Transformations 的核心是 MediatorLiveData 。MediatorLiveData 可以 无限套娃,进行 类型转换 和 多源组合。
【源码分析】- MediatorLiveData
public class MediatorLiveData extends MutableLiveData {
private SafeIterableMap, Source>> mSources = new SafeIterableMap<>();
/**
* 核心思想:添加拦截器(有个这个方法,就可以无限套娃)
*/
@MainThread
public void addSource(@NonNull LiveData source, @NonNull Observer super S> onChanged) {
Source e = new Source<>(source, onChanged);
Source> existing = mSources.putIfAbsent(source, e);
if (existing != null && existing.mObserver != onChanged) {
throw new IllegalArgumentException(
"This source was already added with the different observer");
}
if (existing != null) {
return;
}
if (hasActiveObservers()) {
e.plug();
}
}
@MainThread
public void removeSource(@NonNull LiveData toRemote) {
Source> source = mSources.remove(toRemote);
if (source != null) {
source.unplug();
}
}
@CallSuper
@Override
protected void onActive() { //注释:在有效状态时,进行监听
for (Map.Entry, Source>> source : mSources) {
source.getValue().plug();
}
}
@CallSuper
@Override
protected void onInactive() { //注释:在无效状态时,取消监听
for (Map.Entry, Source>> source : mSources) {
source.getValue().unplug();
}
}
private static class Source implements Observer {
final LiveData mLiveData;
final Observer super V> mObserver;
int mVersion = START_VERSION;
Source(LiveData liveData, final Observer super V> observer) {
mLiveData = liveData;
mObserver = observer;
}
//注释:持久监听,减少没必要的生命周期对象依赖(因为在调用端就已经在活跃状态下)
void plug() {
mLiveData.observeForever(this);
}
void unplug() {
mLiveData.removeObserver(this);
}
@Override
public void onChanged(@Nullable V v) {
//注释:版本有升级,才会进行通知更新
if (mVersion != mLiveData.getVersion()) {
mVersion = mLiveData.getVersion();
mObserver.onChanged(v);
}
}
}
}
3.3 消息总线
LiveData 可以实现 消息总线(事件发布/订阅),但是要解决粘性事件的问题。可以通过反射,修改版本号去除粘性事件分发。具体实现参考 【美团技术团队 - LiveDataBus】。
4. 小结
- 订阅类型:包括受生命周期约束(
observe()
)和不受生命周期约束(observeForever()
)。 - 订阅受生命周期约束的组件,只能与一个
LifecycleOwner
绑定。 - 订阅受生命周期约束的组件,如果
LifecycleOwner
的状态为DESTROYED
,则自动解绑。 - 订阅受生命周期约束的组件,活跃状态切换,分发更新,所以 LiveData 自带粘性事件特征。
- 订阅受生命周期约束的组件,活跃状态切换,分发更新,变更通知(在活跃状态和版本号同时满足的情况下)。
- 属性值更新,分发更新,变更通知(在活跃状态和版本号同时满足的情况下)。
- MediatorLiveData 可以 无限套娃,进行 类型转换 和 多源组合。常用工具类:Transformations 。
小编的博客系列
Jetpack 全家桶