1 简介和简单使用
1.1 简介
LiveData是一种可观察的数据存储器类。与常规的可观察类不同,LiveData具有生命周期感知能力,意指它遵循其他应用组件(如Activity、Fragment或Service)的生命周期。这种感知能力可确保LiveData仅更新处于活跃生命周期(onStart、onResume)状态的应用组件观察者。LiveData通常和ViewModel相结合使用。
LiveData依赖于Lifecycle,需要使用Lifecycle提供的状态来判断程序的活跃状态。
如果观察者(由Observer类表示)的生命周期处于STARTED或RESUMED状态,则LiveData会认为该观察者处于活跃状态。LiveData 只会将更新通知给活跃的观察者。为观察LiveData对象而注册的非活跃观察者不会收到更改通知。
Google官网:https://developer.android.google.cn/topic/libraries/architecture/livedata?hl=zh_cn
1.2 简单使用
引入依赖,按需所取。
def lifecycle_version = "2.4.1"
def arch_version = "2.1.0"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
// Lifecycles only (without ViewModel or LiveData)
implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
// Saved state module for ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
// Annotation processor
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
// alternately - if using Java8, use the following instead of lifecycle-compiler
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
// optional - helpers for implementing LifecycleOwner in a Service
implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"
// optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
// optional - ReactiveStreams support for LiveData
implementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version"
// optional - Test helpers for LiveData
testImplementation "androidx.arch.core:core-testing:$arch_version"
创建一个单例StrLiveData,里边会实例化一个MutableLiveData,用来存储String类型的数据。
object StrLiveData {
//懒加载
val info: MutableLiveData by lazy { MutableLiveData() }
}
在Activity中使用。
class LiveDataActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_live_data)
val tvContent = findViewById(R.id.tv_content)
//观察数据变化,界面可见时,才会给TextView设置数据
StrLiveData.info.observe(this) {
tvContent.text = it
}
//观察数据变化,不管界面可见不可见,都给TextView设置数据
//observeForever不会考虑生命周期,任何状态下都会执行
StrLiveData.info.observeForever {
tvContent.text = it
}
//主线程修改数据
StrLiveData.info.value = "在主线程修改的数据"
thread {
Thread.sleep(2000)
//子线程修改数据
StrLiveData.info.postValue("在子线程修改的数据")
}
}
}
XML文件。
1.3 关系框架
2 源码分析
2.1 setValue 主线程修改数据
首先在业务层单例中实例化了一个MutableLiveData,MutableLiveData继承LiveData,只保留setValue和postValue两个设置数据的方法,简化使用。
public class MutableLiveData extends LiveData {
/**
* 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);
}
}
当业务层调用LiveData的setValue方法时,在主线程修改数据。
//主线程修改数据
StrLiveData.info.value = "在主线程修改的数据"
setValue方法首先会检查当前是否是主线程,然后会对mVersion+1,接着分发数据。
@MainThread protected void setValue(T value) { //检查是否是主线程 assertMainThread("setValue"); //mVersion+1 mVersion++; mData = value; //分发数据 dispatchingValue(null); }
mVersion是LiveData粘性数据特性的关键,它的初始值是-1。
static final int START_VERSION = -1;
public LiveData() {
mData = NOT_SET;
//LiveData实例化的时候给mVersion赋值为-1
mVersion = START_VERSION;
}
分发数据的时候有两种情况,一种是调用LiveData.observe(),另一种是调用LiveData.observeForever()。ObserverWrapper是观察者的包装类。
void dispatchingValue(@Nullable ObserverWrapper initiator) {
...
//initiator(观察者)不为空
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//initiator(观察者)为空,需要遍历所有的观察者
for (Iterator, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
...
}
接下来调用considerNotify方法。然后对当前是否是活跃状态进行检查,也就是mActive是否为true。为true才会继续执行。就这对mVersion进行对比,由于在setValue的时候mVersion++之后变为0,mLastVersion为-1,所以这里observer.mLastVersion >= mVersion不成立,数据会正常分发出去,这就是造成粘性数据特征的原因。
如果调用LiveData.observe(),那么当Lifecycle状态为STARTED和RESUMED,也就是Activity/Fragment生命周期为onStart和onResume的时候,mActive=true,其他状态和生命周期下,mActive=fale;如果调用LiveData.observeForever(),mActive一直为true,这就实现了调用LiveData.observeForever()时候,观察者不会去考虑生命周期和状态,所有数据都会无条件感知。
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
//判断mActivie是否为true。
//调用LiveData.observe()时会根据状态和生命周期计算mActive的值;
//调用LiveData.observeForever()时mActive一直为true。
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//判断mVersion
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//回调数据给观察者
observer.mObserver.onChanged((T) mData);
}
2.2 postValue 子线程修改数据
当业务层调用LiveData的postValue方法时,在子线程修改数据。
thread {
...
//子线程修改数据
StrLiveData.info.postValue("在子线程修改的数据")
}
postValue方法中最终也会通过Handler切换到主线程。
protected void postValue(T value) {
boolean postTask;
//加锁,防止线程安全问题
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
//切换到主线程
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
在ArchTaskExecutor中,会实例化一个DefaultTaskExecutor,然后调用DefaultTaskExecutor的postToMainThread方法。
private ArchTaskExecutor() {
mDefaultTaskExecutor = new DefaultTaskExecutor();
mDelegate = mDefaultTaskExecutor;
}
@Override
public void postToMainThread(Runnable runnable) {
mDelegate.postToMainThread(runnable);
}
DefaultTaskExecutor使用Handler进行线程间通信,实现子线程到主线程切换。
@Override
public void postToMainThread(Runnable runnable) {
if (mMainHandler == null) {
synchronized (mLock) {
if (mMainHandler == null) {
mMainHandler = new Handler(Looper.getMainLooper());
}
}
}
//noinspection ConstantConditions
mMainHandler.post(runnable);
}
而在postToMainThread中传入的Runnable中,最红也调用了setValue,接下来的逻辑就和主线程中修改数据一致了。
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//最终也是调用setValue
setValue((T) newValue);
}
};
2.3 observe 根据生命周期感知数据变化
调用LiveData的observe( LifecycleOwner owner, Observer super T> observer)方法时,传入了一个被观察者和观察者。
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {
//检查是否是主线程
assertMainThread("observe");
//获取Lifecycle当前状态,如果是销毁状态,那就忽略,不再继续往下进行
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
//创建一个LifecycleBoundObserver对象,包装了LifecycleOwner和Observer。
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//ObserverWrapper包装了LifecycleBoundObserver和Observer
//把Observer和LifecycleBoundObserver存入map
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是LiveData的内部类,继承了ObserverWrapper,并且实现LifecycleObserver。传入了一个被观察者和观察者。
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
//传入被观察者和观察者
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
//从Lifecycle获取到当前是否是活跃状态(UI可见状态)。
//Activity/Fragment生命周期onStart和onResume,Lifecycle对应状态为STARTED和RESUMED时,处于活跃状态。
//这里使用了一个比较,也就是状态在STARTED和STARTED之后时,就处于活跃状态。
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
//页面销毁时,移除观察者
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
//调用ObserverWrapper的activeStateChanged,再调用dispatchingValue分发数据。
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
//观察者和被观察者解除绑定
mOwner.getLifecycle().removeObserver(this);
}
}
ObserverWrapper是LiveData的抽象内部类。
private abstract class ObserverWrapper {
final Observer super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
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);
}
}
}
2.3 observeForever 无条件感知数据变化
在调用LiveData的observeForever方法时,没有传入被观察者,值传入了观察者,这就决定了调用observeForever之后无法根据Activity/Fragment的生命周期去判断合适感知数据,只能无条件的接收所有数据。这里用AlwaysActiveObserver对观察者进行了包装。
@MainThread
public void observeForever(@NonNull Observer super T> observer) {
//判断是否是主线程
assertMainThread("observeForever");
//创建一个AlwaysActiveObserver对象,对Observer进行包装
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
//ObserverWrapper包装了AlwaysActiveObserver和Observer
//把Observer和AlwaysActiveObserver存入map
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
//这里传入的mActive一直是true,所以消息一直能无条件回调给观察者
wrapper.activeStateChanged(true);
}
再看AlwaysActiveObserver,shouldBeActive固定返回true。所以在considerNotify方法中,一直能执行到observer.mObserver.onChanged((T) mData),把数据回调给观察者。
private class AlwaysActiveObserver extends ObserverWrapper {
AlwaysActiveObserver(Observer super T> observer) {
super(observer);
}
@Override
boolean shouldBeActive() {
return true;
}
}
3 流程图
根据上边的源码分析,画出以下流程图。
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/19450,转载请注明出处。
评论0