一文搞懂Android-JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧

2. 手动postValue或setValue触发数据通知

接下来,便以这两个任务链的顺序,对每个方法进行分析。

observer()注册监听者

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer 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);
    }

该方法就是把Lifecycle持有对象LifecycleOwner和一个监听者observer传进来,实现这个监听者在这个生命周期作用域下对LiveData的数据进行监听。这里主要的处理是对observer使用Lifecycle的监听者LifecycleBoundObserver进行了封装,并存入管理所有监听者的mObservers中。这里除了过滤避免重复外,还对监听者对应的LifecycleOwner进行了判断,防止一个监听者处于多个Lifecycle作用域进而导致混乱的情况发生。

LifecycleBoundObserver的onStateChanged()

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {

@NonNull
final LifecycleOwner mOwner;

LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer observer) {
super(observer);
mOwner = owner;
}

@Override
boolean shouldBeActive() {
return mOwner.getLifecycle()
.getCurrentState().isAtLeast(STARTED);
}

@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}

@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}

@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}

onStateChanged()的逻辑是LifecycleBoundObserver中对接口LifecycleEventObserver的实现,通过对Lifecycle组件的了解,可以知道在LifecycleOwner的生命周期发生改变时,onStateChanged()方法就会被调用到。这里判断如果LifecycleOwner销毁了,那么就移除这个监听者,达到防止内存泄漏的目的,其它情况则会以shouldBeActivie()为值调用activeStateChanged()方法。shouldBeActivie()判断LifecycleOwner的状态是否处于STARTED之后,也就是是否显示在屏幕中,这里表明了LiveData的另一个特性,默认情况下,显示在屏幕中的页面中的监听者才会收到数据更新的通知。

ObserverWrapper的activeStateChanged()

private abstract class ObserverWrapper {
final Observer mObserver;
boolean mActive;
int mLastVersion = START_VERSION;

ObserverWrapper(Observer observer) {
mObserver = observer;
}

abstract boolean shouldBeActive();

boolean isAttachedTo(LifecycleOwner owner) {
return false;
}

void detachObserver() {
}

void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we’d never dispatch anything to inactive
// owner
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
if (mActive) {
dispatchingValue(this);
}
}
}

activeStateChanged()方法是在LifecycleBoundObserver的父类ObserverWrapper中实现的,先看ObserverWrapper的属性,ObserverWrapper不仅封装了监听者,还用mActive管理是否为活跃状态,以及用mLastVersion管理监听者当前的数据版本。回到activeStateChanged()方法,这里的处理主要分三点,首先,用活跃状态是否发生变化做了一个闭路逻辑,防止重复处理,比如onStart()处理后又接收到onResume()。其次,更新当前状态,并判断如果这是第一个监听者活跃,就调用onActive()方法,如果是最后一个监听者非活跃,就调用onInactive()方法。最后,如果是新的活跃状态,则以当前ObserverWrapper对象为参数值调用dispatchingValue()方法分发事件。

setValue()

@MainThread

protected void setValue(T value) {
assertMainThread(“setValue”);
mVersion++;
mData = value;
dispatchingValue(null);
}

setValue()是LiveData的一个成员方法,用于在主线程中手动更新LiveData中的值,这里先将数据版本mVersion自增后,更新mData的值,并以null为参数值调用dispatchingValue()方法。

postValue()

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() {
@SuppressWarnings(“unchecked”)
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};

postValue()也是用来手动更新LiveData中的值的,不过和setValue()有区别的是,它可以在非主线程中调用。它的处理就是在保证线程安全的前提下,通知主线程调用setValue()方法更新数据。

具体细节是,定义一个volatile修饰的成员变量mPandingData,用作线程间共享数据,这个变量的默认值为NOT_SET。通过对共享数据mPandingData的读写访问进行加锁的方式实现线程安全,同时,主线程读取mPandingData的值后,也就被认为是消费掉了共享数据,这时会把mPandingData设置会默认值NOT_SET,而其他线程在拿到锁后写入mPandingData,也就是生产共享数据时,只有之前主线程已消费掉或还未生产过共享数据,才会向主线程发送处理消息。

这个逻辑实现了另外一个特性,当主线程还没来得及处理消息,这时多个线程同时排队拿锁更新数据,主线程最终只会使用最后最新的数据去处理,调用setValue()通知监听者。

dispatchingValue()

一文搞懂Android-JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧_第1张图片

无论是生命周期回调的activeStateChanged()还是手动发起数据更新setValue(),最终都通过dispatchingValue()完成了数据更新的分发。

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, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}

dispatchingValue()如果传入的参数不为null,那么就针对该对象单独分发,对应的就是生命周期回调的调用。而如果传入了null,那就遍历mObservers,对每一个监听者完成分发。每次分发是调用considerNotify()完成。

dispatchingValue()的处理中首先使用了两个成员变量mDispatchingValue和mDispatchInvalidated做了一个短路逻辑,这俩成员变量分别表示是否处于分发中和分发的数据是否过期。进入分发过程时,会将mDispatchingValue置为true,mDispatchInvalidated置为false,这时表示处于正常的分发状态。如果在正常分发状态时,再有新的分发请求,那么就会将mDispatchInvalidated值为true,正常的分发状态便会中断,重新开始分发。这就实现了一个特性,只对监听者通知最新的数据。

可以使用下面的单元测试加深对该特性的理解。

@Test
public void testSetValueDuringSetValue() {
mOwner.handleLifecycleEvent(ON_START);
final Observer observer1 = spy(new Observer() {
@Override
public void onChanged(String o) {
assertThat(mInObserver, is(false));
mInObserver = true;
if (o.equals((“bla”))) {
mLiveData.setValue(“gt”);
}
mInObserver = false;
}
});
final Observer observer2 = spy(new FailReentranceObserver());
mLiveData.observe(mOwner, observer1);
mLiveData.observe(mOwner, observer2);
mLiveData.setValue(“bla”);
verify(observer1, Mockito.atMost(2))
.onChanged(“gt”);
verify(observer2, Mockito.atMost(2))
.onChanged(“gt”);
}

这个单元测试在源码库中可以找到,有兴趣的同学可以debug一下看看处理流程,后面会介绍一下这个技巧,这里先简单描述一下代码执行过程。

在这个单元测试中,对于mLiveData有两个监听者observer1和observer2,正常情况下,当mLiveData.setValue(“bla”)时,dispatchingValue()对监听者进行遍历,两个监听者应该依次收到数据“bla”的通知,但是observer1在收到“bla”后,又执行mLiveData.setValue(“gt”)发起了新的数据更新,这个第二次dispatchingValue()便会短路,且会中断并重启第一次的遍历,于是observer1会再次收到“gt”,然后才是observer2,它只会收到“gt”。

这个流程便是保证了数据更新只通知最新的,在实际开发中如果遇到setValue()的过程中再次setValue()的情况,就需要特别注意一下这条特性。

considerNotify()

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);
}

considerNotify()才是最终发起数据更新通知的方法,这里首先检查了监听者及其所处生命周期的活跃状态,并比较了监听者的数据版本和当前数据版本,保证了监听者所在页面处于前台时并且数据版本需要更新时才发起通知。发起通知前会更新监听者的数据版本到最新,确保数据一致。

LiveData特性

分析完这些主要方法后,便可以对LiveData的特性做一个总结了,以便在实际使用过程中更加得心应手。

1. 一个监听者只能处于一个生命周期作用域中

2. 监听者通过Lifecycle的特性实现页面销毁后自动注销,防止内存泄漏

3. 监听者只会在所处的页面在前台的情况下收到数据更新的通知

4. 由于Lifecycle的特性,监听者如果在所处页面在前台的情况下,注册进LiveData,会立即调用到considerNotify(),这时候如果LiveData的数据版本变化过,便会立即对该监听者发送通知,这也就是所谓的粘性事件。

5. postValue()经过线程安全处理,最终通过setValue()发起数据更新通知。N次postValue()并不能保证同样N次setValue(),post中防止了重复向主线程发消息,主线程中只会拿当前最新的值调用setValue()。

6. N次setValue()同样不能保证活跃的监听者被通知到N次,LiveData保证了只通知最新的数据。

自顶向下分析总结

自顶向下方法主要难点在于从类关系图中找出要分析的核心方法及其调用关系链,这需要提前对该组件有一定的理解,本次LiveData的分析先使用了软件过程的三个角度框定了方法范围,再通过在源码快速跳转的方式整理出调用链,大家可以在自己分析时参考。确定了要分析的方法后,接下来就是细心的分析工作,需要注意的是在这个过程中要总结出其实现的特性,从而更好地指导在日常实际开发工作。

03逐类分析

逐类分析的方式适合对一个组件不了解的情况下使用,以期快速地掌握大概原理。整个过程就是以总结类功能为目的,对组件的相关类逐个通过跳转方法进入,快速阅读并做出总结,掌握类功能定义,为以后使用其它方式进一步理解源码做好准备。下面以这个方式分析一下ViewModel的源码。

首先,还是先看一个例子:

public class MyViewModel extends ViewModel {
private MutableLiveData users;
public LiveData getUsers() {
if (users == null) {
users = new MutableLiveData();
loadUsers();
}
return users;
}

private void loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
MyViewModel model = new ViewModelProvider(this).get(MyViewModel.class);
}
}

该例子定义了一个ViewModel的子类MyViewModel,然后通过ViewModelProvider的实例方法get()获取到MyViewModel的实例。

ViewModelProvider

/**

  • Creates {@code ViewModelProvider}. This will create {@code ViewModels}
  • and retain them in a store of the given {@code ViewModelStoreOwner}.
  • This method will use the
  • {@link HasDefaultViewModelProviderFactory#getDefaultViewModelProviderFactory() default factory}
  • if the owner implements {@link HasDefaultViewModelProviderFactory}. Otherwise, a
  • {@link NewInstanceFactory} will be used.
    /
    public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
    this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
    ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
    : NewInstanceFactory.getInstance());
    }
    /
    *
  • Creates {@code ViewModelProvider}, which will create {@code ViewModels} via the given
  • {@code Factory} and retain them in the given {@code store}.
  • @param store {@code ViewModelStore} where ViewModels will be stored.
  • @param factory factory a {@code Factory} which will be used to instantiate
  •            new {@code ViewModels}
    

*/
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
mViewModelStore = store;
}

从构造方法中可以看出ViewModelProvider需要ViewModelStore和Factory两个类型的成员变量才能构造处理,分别是mViewModelStore和mFactory,ComponentActivity和Fragment分别都实现了ViewModelStoreOwner和HasDefaultViewModelProviderFactory接口,所以都可以从中获取到ViewModelStore和Factory的实例。

@NonNull
@MainThread
public T get(@NonNull Class modelClass) {
String canonicalName = modelClass.getCanonicalName();
if (canonicalName == null) {
throw new IllegalArgumentException(“Local and anonymous classes can not be ViewModels”);
}
return get(DEFAULT_KEY + “:” + canonicalName, modelClass);
}
@MainThread
public T get(@NonNull String key, @NonNull Class modelClass) {
ViewModel viewModel = mViewModelStore.get(key);

if (modelClass.isInstance(viewModel)) {
if (mFactory instanceof OnRequeryFactory) {
((OnRequeryFactory) mFactory).onRequery(viewModel);
}
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
} else {
viewModel = mFactory.create(modelClass);
}
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}

get()方法首先尝试通过mViewModelStore的get()方法获取ViewModel的实例,如果没获取到则使用mFactory的create()创建实例,创建出来后则存入到mViewModelStore中。在这里mFactory就是ViewModel的构造工厂,mViewModelStore则是ViewModel的缓存管理者。

ViewModelProvider作为ViewModel的提供者,使用缓存mViewModelStore和工厂mFactory实现,第一次提供ViewModel时会通过工厂创建出来,后续则都是从缓存中拿。

ViewModelStore

public ComponentActivity() {


getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
}
@NonNull
@Override
public ViewModelStore getViewModelStore() {
if (getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the "

  • “Application instance. You can’t request ViewModel before onCreate call.”);
    }
    if (mViewModelStore == null) {
    NonConfigurationInstances nc =
    (NonConfigurationInstances) getLastNonConfigurationInstance();
    if (nc != null) {
    // Restore the ViewModelStore from NonConfigurationInstances
    mViewModelStore = nc.viewModelStore;
    }
    if (mViewModelStore == null) {
    mViewModelStore = new ViewModelStore();
    }
    }
    return mViewModelStore;
    }

ViewModelStoreOwner接口getViewModelStore()的实现就是提供一个ViewModelStore实例,而ComponentActivity使用Lifecycle能力在页面销毁时调用ViewModelStore实例的clear方法,清空其中的ViewModel。

public class ViewModelStore {

private final HashMap mMap = new HashMap<>();

final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}

final ViewModel get(String key) {
return mMap.get(key);
}

Set keys() {
return new HashSet<>(mMap.keySet());
}

/**

  • Clears internal storage and notifies ViewModels that they are no longer used.
    */
    public final void clear() {
    for (ViewModel vm : mMap.values()) {
    vm.clear();
    }
    mMap.clear();
    }
    }

ViewModelStore中使用HashMap管理ViewModel缓存,它被页面持有,并在页面真正销毁时才清空缓存。

官网的这张图中可以说明ViewModel的生命周期。

一文搞懂Android-JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧_第2张图片

SaveStateViewModelFactory

public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {

if (getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the "

  • “Application instance. You can’t request ViewModel before onCreate call.”);
    }
    if (mDefaultFactory == null) {
    mDefaultFactory = new SavedStateViewModelFactory(
    getApplication(),
    this,
    getIntent() != null ? getIntent().getExtras() : null);
    }
    return mDefaultFactory;
    }

ComponentActivity中getDefaultViewModelProviderFactory()方法通过构造方法创建一个SavedStateViewModelFactory对象,传入了Application、当前ComponentActivity实例和Intent中的数据bundle。

SavedStateViewModelFactory构造方法

public SavedStateViewModelFactory(@NonNull Application application,
@NonNull SavedStateRegistryOwner owner,
@Nullable Bundle defaultArgs) {
mSavedStateRegistry = owner.getSavedStateRegistry();
mLifecycle = owner.getLifecycle();
mDefaultArgs = defaultArgs;
mApplication = application;
mFactory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}

构造方法接受的参数中,页面实例是SavedStateRegistryOwner接口类型的,通过该接口获取到SavedStateRegistry和Lifecycle。另外成员变量mFactory是AndroidViewModelFactory的单例对象。

SavedStateViewModelFactory的create()

@Override
public T create(@NonNull String key, @NonNull Class modelClass) {
boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
Constructor constructor;
if (isAndroidViewModel) {
constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
} else {
constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
}
// doesn’t need SavedStateHandle
if (constructor == null) {
return mFactory.create(modelClass);
}

SavedStateHandleController controller = SavedStateHandleController.create(
mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
try {
T viewmodel;
if (isAndroidViewModel) {
viewmodel = constructor.newInstance(mApplication, controller.getHandle());
} else {
viewmodel = constructor.newInstance(controller.getHandle());
}
viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
return viewmodel;
} catch (IllegalAccessException e) {
throw new RuntimeException("Failed to access " + modelClass, e);
} catch (InstantiationException e) {
throw new RuntimeException(“A " + modelClass + " cannot be instantiated.”, e);
} catch (InvocationTargetException e) {
throw new RuntimeException("An exception happened in constructor of "

  • modelClass, e.getCause());
    }
    }

create()方法支持创建三种类型的ViewModel:AndroidViewModel、支持SavedState的ViewModel、普通ViewModel,这里由于篇幅原因,只分析一下普通ViewModel的创建。普通ViewModel通过mFactory的create()方法创建出来。

AndroidViewModelFactory的create()

public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory {


@NonNull
@Override
public T create(@NonNull Class modelClass) {
if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
//noinspection TryWithIdenticalCatches
try {
return modelClass.getConstructor(Application.class).newInstance(mApplication);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InstantiationException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
}
}
return super.create(modelClass);
}
}

AndroidViewModelFactory的create()方法判断如果不是AndroidViewModel类型,就直接通过父类的create()方法创建,而AndroidViewModelFactory的父类是NewInstanceFactory。

NewInstanceFactory的create()

public static class NewInstanceFactory implements Factory {

@SuppressWarnings(“ClassNewInstance”)
@NonNull
@Override
public T create(@NonNull Class modelClass) {
//noinspection TryWithIdenticalCatches
try {
return modelClass.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
}
}
}

NewInstanceFactory的create()则是直接通过反射创建出ViewModel实例。

SaveStateViewModelFactory作为ComponentActivity和Fragment提供的对象,在NewInstanceFactory的基础上增加了对AndroidViewModel和支持SavedStated的ViewModel的创建,但对于普通的ViewModel创建,最后还是降级使用NewInstanceFactory完成。

到此,ViewModel的主要类已经分析完了,接下来可以结合类关系,一定程度上总结出对全局视角的理解。

一文搞懂Android-JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧_第3张图片

主要类说明:

  • ViewModelProvider:ViewModel提供者
  • ViewModelStore:ViewModel缓存管理
  • ViewModelProvider.Factory:ViewModel创建工厂
  • SavedStateViewModelFactory:ViewModel创建工厂的实现
  • NewInstanceFactory:普通ViewModel创建工厂的实现

类关系描述:

ViewModel通过ViewModelProvider的get()方法获取到,ViewModelProvider由缓存ViewModelStore和创建工厂ViewModelProvider.Factory组合而成,ViewModelStore和ViewModelProvider.Factory也是ComponentActivity的一部分,ComponentActivity通过实现ViewModelStoreOwner和HasDefaultViewModelProviderFactory两个接口对外提供ViewModelStore和ViewModelProvider.Factory。其中,ViewModelProvider.Factory在ComponentActivity的具体实现是SavedStateViewModelFactory,SavedStateViewModelFactory一部分由AndroidViewModelFactory组合而成,它提供创建三种ViewModel的能力,其中普通ViewModel的创建是由AndroidViewModelFactory的父类NewInstanceFactory完成。

逐类分析方法总结

逐类分析重点在于抓大放小,分析每个类的主要目的是掌握该类的功能定位,达到目的即可,不要深陷到源码细节中。在快速分析完后,结合相关的类做出总结,从而获得整体上的了解,为以后进一步源码原理分析打好基础。

源码分析技巧

Android Jetpack是一个比较新的开源库,有几个技巧可以提高分析的效率,比如查看代码提交记录和使用单元测试。

01查看代码提交记录

比如Lifecycling的lifecycleEventObserver()方法比较复杂,刚开始不太能理解这个方法封装注解解析后的监听者那部分逻辑。可以使用以下方法查看这几行的提交记录,方便理解。

查看Annotate:

一文搞懂Android-JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧_第4张图片

点击相关行,查看提交信息

一文搞懂Android-JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧_第5张图片

双击相关类,查看改动记录

一文搞懂Android-JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧_第6张图片

在改动记录中,还可以继续查看Annotation,理解原有的功能

一文搞懂Android-JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧_第7张图片

可以使用该技巧先理解旧功能是什么样的,从而对比出这次改动所增加的特性。

以本例来说,可以看出旧getObserverConstructorType()方法是直接返回构造对象,这个构造对象可能是注解处理器生成的类的,也可能是普通监听者需要用反射处理的类的,然后用这个构造对象创建出监听器的封装。而这次修改了getObserverConstructorType()返回为解析后的结果类型,包括REFLECTIVE_CALLBACK和GENERATED_CALLBACK,再用这个类型和getObserverConstructorType()方法中解析的缓存判断应该创建哪个监听器的封装对象。这次增加的功能点是对实现多个LifecycleObserver接口的监听器的支持,可以在单元测试类GeneratedAdapterTest中找到具体使用示例。

interface OnPauses extends LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
void onPause();

@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
void onPause(LifecycleOwner owner);
}

interface OnPauseResume extends LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
void onPause();

@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
void onResume();
}

class Impl1 implements OnPauses, OnPauseResume {

List mLog;

Impl1(List log) {
mLog = log;
}

@Override
public void onPause() {
mLog.add(“onPause_0”);
}

@Override
public void onResume() {
mLog.add(“onResume”);
}

@Override
public void onPause(LifecycleOwner owner) {
mLog.add(“onPause_1”);
}
}

比如上面的Impl1实现了OnPauses和OnPauseResume两个LifecycleObserver接口,这次增加的功能点就是对Impl1也可以使用注解解析器生成封装类,以优化性能。

02使用单元测试用例

JetPack中的单元测试非常丰富,而且从提交信息中一般都可以看到本次改动对应修改的单元测试类,比如上面的例子中,Commit Message可以看到“Test: GeneratedAdaptersTest”,可以很快定位到该单元测试,再加上断点调试的手段,更快地理解源码。

比如,之前一直有提到注解解析器生成的监听器封装类,那这个类具体代码是什么样的呢,就可以在GeneratedAdaptersTest找到使用注解的实例,再通过断点找到这个类。

一文搞懂Android-JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧_第8张图片

debug运行testOnAny()测试

一文搞懂Android-JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧_第9张图片

通过堆栈可以定位到GeneratedAdaptersTest_TestObserver_LifecycleAdapter类,

public class GeneratedAdaptersTest_TestObserver_LifecycleAdapter implements GeneratedAdapter {
final GeneratedAdaptersTest.TestObserver mReceiver;

GeneratedAdaptersTest_TestObserver_LifecycleAdapter(GeneratedAdaptersTest.TestObserver receiver) {
this.mReceiver = receiver;
}

@Override
public void callMethods(LifecycleOwner owner, Lifecycle.Event event, boolean onAny,
MethodCallsLogger logger) {
boolean hasLogger = logger != null;
if (onAny) {
if (!hasLogger || logger.approveCall(“onAny”, 1)) {
mReceiver.onAny();
}
return;
}
if (event == Lifecycle.Event.ON_CREATE) {
if (!hasLogger || logger.approveCall(“onCreate”, 1)) {
mReceiver.onCreate();
}
return;
}
}
}

该类既是注解解析器生成的监听器封装类,它的callMethods()方法的实现由TestObserver的注解决定,TestObserver中使用了ON_CREATE和ON_ANY注解,所以除了onAny为true的情况,callMethods()只回调监听者的onCreate()方法。

注解处理器的实现可以定位到lifecycle-compiler项目中看,这里限于篇幅就不展开了。

一文搞懂Android-JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧_第10张图片

总结

最后

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

同时我经过多年的收藏目前也算收集到了一套完整的学习资料以及高清详细的Android架构进阶学习导图及笔记免费分享给大家,希望对想成为架构师的朋友有一定的参考和帮助。

下面是部分资料截图,诚意满满:特别适合有开发经验的Android程序员们学习。

一文搞懂Android-JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧_第11张图片

资料免费领取方式:点击我的GitHub~

不论遇到什么困难,都不应该成为我们放弃的理由!

bserver中使用了ON_CREATE和ON_ANY注解,所以除了onAny为true的情况,callMethods()只回调监听者的onCreate()方法。

注解处理器的实现可以定位到lifecycle-compiler项目中看,这里限于篇幅就不展开了。

[外链图片转存中…(img-h3KLYZqp-1643965101916)]

总结

最后

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

同时我经过多年的收藏目前也算收集到了一套完整的学习资料以及高清详细的Android架构进阶学习导图及笔记免费分享给大家,希望对想成为架构师的朋友有一定的参考和帮助。

下面是部分资料截图,诚意满满:特别适合有开发经验的Android程序员们学习。

[外链图片转存中…(img-DG00wvMN-1643965101917)]

资料免费领取方式:点击我的GitHub~

不论遇到什么困难,都不应该成为我们放弃的理由!

如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言,一定会认真查询,修正不足,谢谢。

你可能感兴趣的:(程序员,架构,移动开发,android)