概述
1、前言
最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面。
Android Architecture组件是Android Jetpack的一部分,它们是一组库,旨在帮助开发者设计健壮、可测试和可维护的应用程序,包含一下组件:
- 带你领略Android Jetpack组件的魅力
- Android Jetpack 架构组件之 Lifecycle(使用篇)
- Android Jetpack 架构组件之 Lifecycle(源码篇)
- Android Jetpack 架构组件之 ViewModel (源码篇)
- Android Jetpack 架构组件之 LiveData(使用、源码篇)
- Android Jetpack架构组件之 Paging(使用、源码篇)
- Android Jetpack 架构组件之 Room(使用、源码篇)
- Android Jetpack 架构组件之Navigation
- Android Jetpack架构组件之WorkManger
- 实战:从0搭建Jetpack版的WanAndroid客户端
上述时Android Architecture所提供的架构组件,本文主要从使用和源码的角度了解一下LiveData组件
2、LiveData简介
- LiveData是一个具有生命周期感知特性的可观察的数据保持类,使用LiveData保存数据时,在每次订阅或数据更新时会自动回调设置的观察者从而更新数据,真正的实现了数据驱动的效果
- LiveData的创建基本会在ViewModel中,从而使数据在界面销毁时继续保持
- LiveData 认为观察者的生命周期处于STARTED状态或RESUMED状态下,表示观察者处于活动状态,LiveData只通知活跃的观察者更新数据
- 注册一个实现该LifecycleOwner 接口的对象配对的观察者,当相应Lifecycle对象的状态改变为DESTROYED时移除观察者
3、LiveData的使用
- 创建一个LiveData实例来保存某种类型的数据
class TestViewModel : ViewModel() {
var mCurrent: MutableLiveData<String>? = null
get() {
if (field == null) {
field = MutableLiveData()
}
return field
}
}
- 请确保存储LiveData对象是在ViewModel中而不是活动或片段
- 创建一个定义onChanged()方法的Observer对象,在数据变化时回调
//创建观察者对象
val nameObservable = Observer<String> { // 创建观察者对象
textView.text = it // 定义onChange()方法中的操作
}
- 使用LifecycleOwner的observe() 方法将观察者对象附加到LiveData对象,这将观察对象向LiveData对象订阅,以便通知其更改
// 如果在View Model中使用,先创建ViewModel的对象
mModel = ViewModelProviders.of(this).get(TestViewModel::class.java)
// mCurrent 订阅观察
mModel.mCurrent!!.observe(this, nameObservable)
- 第一个参数传递的this就是LifecycleOwner 的实例,LiveData会根据Owner的声明周期自动作相应的处理
- observe()将nameObservable作参数调用后,如果LiveData数据有值,onChange()立即调用获取最新值
- 可以使用observeForever(Observer)方法注册一个没有关联的生命周期所有者对象的观察者,在这种情况下,观察者被认为总是活动的,因此总是通知修改,可以删除这些观察员调用removeObserver(Observer) 方法
- LiveData允许UI控制器观察员订阅更新
// 设置两个点击事件,修改LiveData中的数据
btnChange.setOnClickListener { mModel.mCurrent!!.value = "AAAAA" }
btnB.setOnClickListener { mModel.mCurrent!!.value = "BBBBB" }
- 当LiveData对象保存的数据发生变化时,UI会自动响应更新
- 观察者在从非活动状态变为活动状态时也会收到更新
- 运行结果:点击按钮后改变LiveData的数据,界面的TextView也随之改变
4、转换LiveData
- Transformations.map():对存储在LiveData对象中的值应用函数,并将结果传播到下游
// 将返回开始示例中的 mCurrent 值的长度
var liveDataMap: LiveData<Int> = Transformations.map<String, Int>(mCurrent) { input: String -> input.length }
- Transformations.switchMap() :第二个参数返回 一个LiveData
var livaDataSwich : LiveData<String> = Transformations.switchMap<String,String>(mCurrent){
input: String? -> MutableLiveData<String>().also { it.value = input!!.toLowerCase() }
}
- 对上面转换的LiveData订阅观察
val lowObservable = Observer<String> {
textViewLow.text = it
}
val lengthObservable = Observer<Int> {
textViewLength.text = it.toString()
}
mModel.liveDataMap.observe(this, lengthObservable)
mModel.livaDataSwich.observe(this, lowObservable)
- 使用场景
- 将LiveData对象分发给观察者之前对其中存储的值进行更改
- 需要LiveData根据另一个实例的值返回其他 实例
- 当基础的LiveData改变时,转换后的LiveData也会改变并且触发UI更新
5、扩展LiveData
public class LocationLiveData extends LiveData<Location> {
private static LocationLiveData sInstance;
private LocationManager locationManager;
@MainThread
public static LocationLiveData get(Context context) {
if (sInstance == null) {
sInstance = new LocationLiveData(context.getApplicationContext());
}
return sInstance;
}
private SimpleLocationListener listener = new SimpleLocationListener() {
@Override
public void onLocationChanged(Location location) {
setValue(location);
}
};
private LocationLiveData(Context context) {
locationManager = (LocationManager) context.getSystemService(
Context.LOCATION_SERVICE);
}
@Override
protected void onActive() {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
}
@Override
protected void onInactive() {
locationManager.removeUpdates(listener);
}
}
- onActive() :当LiveData对象具有活动观察者时调用该方法
- onInactive() :当LiveData对象没有任何活动观察者时调用该方法
- setValue(T) :方法更新LiveData实例的值,并通知任何活动的观察者有关更改的信息
上面代码使用单例提供LocationLiveData可以在Activity和Fragment之间实现共享,在onActive和onInactive中完成监听的注册和取消,当位置改变时回调Listener并调用setValue()设置LiveData的值,从而自动更新观察者中的数据,其实前面使用的MutableLiveData也是同样的一个扩展
- 使用扩展LIveData
扩展的LiveData使用和正常使用一样,observe()方法将Fragmrnt(它是一个实例LifecycleOwner)作为第一个参数传递,使观察者绑定到Fragment的生命周期,如果Lifecycle对象未处于活动状态,则即使值发生更改,也不会调用观察者,在之后Lifecycle的对象被Destroy后,观察者被自动删除
6、源码分析
- MutableLiveData
public class MutableLiveData<T> extends LiveData<T> {
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
从代码中可以看出MutableLiveData知识LiveData的一个扩展类,重写了LiveData中的抽象方法,postValue()和setValue()中也只是调用了super.postValue()和super.setValue(),也就是说所有的方法都是在LiveData中实现,
- LiveData.observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer)
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
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);
}
从第一步添加观察者observe方法开始,从参数中看到了LifecycleOwner,相信看过Lifecycler源码的(Android Jetpack框架之 Lifecycle(源码篇))应该会想到这里的作用是处理生命周期改变,在observe方法中执行了以下逻辑:
- 在observe中首先判断了当前Lifecycler的状态,当Destroy时即观察者不处于活跃状态,不用接收数据
- 创建LifecycleBoundObserver实例保存传入的LifecycleOwner和Observer,并保存在mObservers
- 添加LifecycleOwner的观察者,响应生命周期的变化
- ObserverWrapper & LifecycleBoundObserver
private abstract class ObserverWrapper {
final Observer<T> mObserver;
ObserverWrapper(Observer<T> observer) {
mObserver = observer; // 保存观察者Observer
}
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive(); // 当Owner为活跃状态时回调onActive()
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive(); // 当Owner未活跃状态时回调onInactive()
}
if (mActive) {
dispatchingValue(this);
}
}
}
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver { //
@NonNull final LifecycleOwner mOwner; //保存LifecycleOwner
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
super(observer); // 调用父类ObserverWrapper的构造函数传递Owner
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
// 实现GenericLifecycleObserver 当生命周期改变时回调onStateChanged
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver); // DESTROYED时移除观察者
return;
}
activeStateChanged(shouldBeActive());
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
上述执行的逻辑见代码中的注释,ObserverWrapper 在Owner活跃状态改变时回调onActive和onInactive方法,LifecycleBoundObserver主要利用Lifecycler的生命周期观察者GenericLifecycleObserver,前面设置了owner.getLifecycle().addObserver(wrapper)后,当生命周期改变时会回调onStateChange()方法,在生命周期为Destroy时移除Observer,在每次的生命周期变化时都会回调onStateChange(),然后调用shouldBeActive()判断当前活动是否出入活跃状态,shouldBeActive会根据Lifecycle中定义生命周期的顺序检测,只有当大于STARTED生命周期才为活跃,在activeStateChanged()也只会在活跃状态分发数据,然后调用dispatchingValue()分发数据;
- setValue(T value)
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
}
setValue()中调用了dispatchingValue(),在dispatchingValue中遍历mObservers中所有的Observer,调用considerNotify()更新数据,由前面知道所有的LifecycleBoundObserver对象都保存在mObservers集合中
- considerNotify()
private void considerNotify(ObserverWrapper observer) {
observer.mObserver.onChanged((T) mData);
}
considerNotify()中调用mObserver的onChange()方法,这里的mObserver就是前面observe()中第二个参数的Observer,从而更新数据,简单就是说当LiveData中的数据改变时会遍历此LiveData所有的观察者,并回调onChange(),所以所有注册观察此数据的地方都会改变
- postValue(T value)
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
setValue((T) newValue);
}
};
postValue()其实是在非主线程中更新数据,其实他传递的Runnable中也是调用了setValue()方法,其余的操作只是通过ArchTaskExecutor和DefaultTaskExecutor将操作切换到主线程。
- map()转换的源码分析
public static <X, Y> LiveData<Y> map(@NonNull LiveData<X> source,
@NonNull final Function<X, Y> func) {
final MediatorLiveData<Y> result = new MediatorLiveData<>(); //创建MediatorLiveData实例
result.addSource(source, new Observer<X>() { //调用MediatorLiveData.addSource传入LiveData和观察者
@Override
public void onChanged(@Nullable X x) {
result.setValue(func.apply(x)); //在观察者回调中重新设着result的值,触发result的响应
}
});
return result;
}
在调用Transformations.map()方法后,系统会先创建一个MediatorLiveData对象,MediatorLiveData也是LiveData的实例,从上面的代码大致可以看出map()的工作原理,
- 首先创建MediatorLiveData实例,然后调用addSource()方法添加原数据对象source,新创建的观察者Observer,
- 在观察者的onChange()方法中调用setValue()重新设置MediatorLiveData的result的值,此处设置的值是经过转换方法处理后的数据,在setValue()后就触发了转换后数据的更新
//MediatorLiveData.addSource()
@MainThread
public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<S> onChanged) {
Source<S> e = new Source<>(source, onChanged); // 封装原数据LiveData和观察者Observer
Source<?> existing = mSources.putIfAbsent(source, e);
if (hasActiveObservers()) {
e.plug(); //调用Source.plug()添加观察者
}
}
在将原数据LiveData和传入的Observer封装在Source中,然后缓存在mSources中,然后调用Source.plug()为Source添加观察者
private static class Source<V> implements Observer<V> {
final LiveData<V> mLiveData;
final Observer<V> mObserver;
int mVersion = START_VERSION;
Source(LiveData<V> liveData, final Observer<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); // 在永久观察的回调方法中回调Observer.onChange()
}
}
}
在Source类中保存这传入的LivaData和Observer,然后调用plugin()方法为LiveData添加本地观察者,在原数据mLivaData发生改变时回调onChange,在onChange()中回调保存的Observer中的方法,此处执行的是在map()中匿名创建的Observer,由上面知道在Observer中调用了修改数据的方法并重新设置数据,从而更新掉map转换的数据
- switchMap():源码和map的逻辑相似,只不过是多了一层数据的设置
@MainThread
public static <X, Y> LiveData<Y> switchMap(@NonNull LiveData<X> trigger,
@NonNull final Function<X, LiveData<Y>> func) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(trigger, new Observer<X>() {
LiveData<Y> mSource;
@Override
public void onChanged(@Nullable X x) {
LiveData<Y> newLiveData = func.apply(x);
if (mSource == newLiveData) {
return;
}
if (mSource != null) {
result.removeSource(mSource);
}
mSource = newLiveData;
if (mSource != null) {
result.addSource(mSource, new Observer<Y>() {
@Override
public void onChanged(@Nullable Y y) {
result.setValue(y);
}
});
}
}
});
return result;
}
- observeForever()源码分析
从名字上即可看出它的作用,普通的监听方法只会在活动处于活跃状态,即处于Started和Destory之间才会分发数据,而observeForever会在任何时候都会分发数据,它的实现逻辑很简单只是重写了上面的shouldBeActive()方法,使之总是返回true
private class AlwaysActiveObserver extends ObserverWrapper {
AlwaysActiveObserver(Observer<T> observer) {
super(observer);
}
@Override
boolean shouldBeActive() {
return true;
}
}
LiveData的使用和源码分析到此结束了,LiveData整个过程就是两部分,一是使用LifeCycleOwner感知声明周期的变化,两一个就是储存并遍历Observer,在数据改变时回调所有的观察者,LiveData的实现还是比较简单的,希望本篇文章的分析对大家有所帮助。
最后
以上就是瘦瘦时光为你收集整理的Android Jetpack架构组件之 LiveData(使用、源码篇)的全部内容,希望文章能够帮你解决Android Jetpack架构组件之 LiveData(使用、源码篇)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复