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

static class CallbackInfo {

final Map<Lifecycle.Event, List> mEventToHandlers;

final Map<MethodReference, Lifecycle.Event> mHandlerToEvent;

CallbackInfo(Map<MethodReference, Lifecycle.Event> handlerToEvent) {

mHandlerToEvent = handlerToEvent;

mEventToHandlers = new HashMap<>();

for (Map.Entry<MethodReference, Lifecycle.Event> entry : handlerToEvent.entrySet()) {

Lifecycle.Event event = entry.getValue();

List methodReferences = mEventToHandlers.get(event);

if (methodReferences == null) {

methodReferences = new ArrayList<>();

mEventToHandlers.put(event, methodReferences);

}

methodReferences.add(entry.getKey());

}

}

@SuppressWarnings("ConstantConditions")

void invokeCallbacks(LifecycleOwner source, Lifecycle.Event event, Object target) {

invokeMethodsForEvent(mEventToHandlers.get(event), source, event, target);

invokeMethodsForEvent(mEventToHandlers.get(Lifecycle.Event.ON_ANY), source, event,

target);

}

private static void invokeMethodsForEvent(List handlers,

LifecycleOwner source, Lifecycle.Event event, Object mWrapped) {

if (handlers != null) {

for (int i = handlers.size() - 1; i >= 0; i--) {

handlers.get(i).invokeCallback(source, event, mWrapped);

}

}

}

}

CallbakcInfo在创建时,会解析hanlderToEvent,把一个MethodReference对应一个event的关系,转化为一个event对应多个MethodReference,并存入到mEventToHandlers中。这样在被调用invokeCallbacks()方法时,只需要从mEventToHandlers中取出对应的MethodReference,就可以回调监听者了。

static final class MethodReference {

final int mCallType;

final Method mMethod;

MethodReference(int callType, Method method) {

mCallType = callType;

mMethod = method;

mMethod.setAccessible(true);

}

void invokeCallback(LifecycleOwner source, Lifecycle.Event event, Object target) {

//noinspection TryWithIdenticalCatches

try {

switch (mCallType) {

case CALL_TYPE_NO_ARG:

mMethod.invoke(target);

break;

case CALL_TYPE_PROVIDER:

mMethod.invoke(target, source);

break;

case CALL_TYPE_PROVIDER_WITH_EVENT:

mMethod.invoke(target, source, event);

break;

}

} catch (InvocationTargetException e) {

throw new RuntimeException("Failed to call observer method", e.getCause());

} catch (IllegalAccessException e) {

throw new RuntimeException(e);

}

}

...

}

invokeCallback()就是根据callType对mMethod进行反射调用,最终执行到Lifecycling.lifecycleEventObserver()传入的监听器的方法实现中。

到此,Lifecycle的基本流程已经分析完了。接下来,可以使用类图对Lifecycle的处理流程做下总结。

类关系图

该图使用simpleUML工具生成

用最初的使用代码来解释一下这个类图。

lifecycleOwner.getLifecycle().addObserver(new MyObserver());

首先,通过LifecycleOwner拿到Lifecycle示例,LifecycleOwner是提供获取Lifecycle实例的接口,一般ComponentActvitiy和Fragment会实现这个接口,这个新旧代码有些差别,使用时需要区分。

然后,Lifecycle实例一般具体类型是LifecycleRegistry,它里面使用State管理当前的生命周期状态,同时每个监听者LifecycleObserver也都有一个State,表示监听者当前的状态,生命周期事件Event发生后,会在LifecycleRegistry内与State发生互相转化,再使用这个转化后最新的State,与所有监听者的State比较,到达完整无误地通知监听者生命周期事件的目的。

最后,监听者注册进Lifecycle时,一般情况下会使用ReflectiveGenericLifecycleObserver封装,ReflectiveGenericLifecycleObserver本身也是LifecycleObserver接口的实现,它还封装了从传入监听者类中解析的CallbackInfo,在被通知生命周期事件时,会使用CallbackInfo反射调用到用户声明的接口方法实现上。

自底向上方法总结

自底向上的方式分析源码主要在于分析前问题的提出,上面应用了软件过程中的输入、处理和输出这三个角度提出问题,算是比较通用的一种方式。问题提出后,便可以以解决问题为目的分析源码,不至于在茫茫源码中迷失了方向。解决完问题,紧接着把源码的主要流程梳理一遍,做出总结,即可以加深对原理的理解。

02自顶向下

自顶向下分析源码与自底向上在思路上正好相反,需要先绘制出组件的类关系图,然后抽出主要方法,进一步解析方法,从而掌握实现细节,它适合于在对源码组件有一个整体上的了解前提下进行,可以深刻掌握组件的原理特性。接下来就使用该方法总结出LiveData的特性。

首先还是以一个示例开始:

MutableLiveData liveString = new MutableLiveData<>();

liveString.observe(mOwner, new Observer() {

@Override

public void onChanged(@Nullable final String s) {

Log.d(TAG, "onChanged() called with: s = [" + s + "]");

}

});

liveString.setValue("LiveData使用案例");

该例子包含了使用LIveData的基本三部分:定义、注册监听者、更新数据。可以同样以软件过程的输入、处理和输出三个角度为切入点进行分析。处了定义外,监听者相关的操作可以看作是输出,比如注册、回调、注销。更新数据则可以看作是输入,而处理则是在LiveData的内部完成。

类关系图

LiveData的类关系图并不复杂,它只有5个类,除了示例中已经出现的有Observer和MutableLiveData,而主要类LiveData则包含和处理的主要逻辑,LiveData的内部类ObserverWrapper和LifecycleBoundObserver则提供了封装Observer和Lifecycle生命周期管理的能力。这里也可以看出LiveData依赖Livecycle的关系。

可以从类图中抽出需要分析的方法,回到输入、处理和输出的角度,对应的就是数据更新、数据流转和监听者处理三类方法。

输入-数据更新:postValue()、setValue()、onStateChanged()

处理-数据流转:activeStateChanged()、dispatchingValue()、considerNotify()

输出-监听者处理:observe()、removeObserver()、onChanged()

接下来,可以使用在源码方法间快速跳转的方式,手动定位并列出相应处理链。

从该图中可以看出触发数据通知的两个处理链:

  1. 注册监听者后,可以接收到Lifecycle事件,这时候可能会移除监听者,也可能触发了数据通知

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

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

observer()注册监听者

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

该方法就是把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<? super T> 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<? 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;

}

// 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()

无论是生命周期回调的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<Map.Entry<Observer<? super T>, 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<List> users;

public LiveData<List> getUsers() {

if (users == null) {

users = new MutableLiveData<List>();

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<String, ViewModel> 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的生命周期。

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的主要类已经分析完了,接下来可以结合类关系,一定程度上总结出对全局视角的理解。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。






既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)

尾声

面试成功其实都是必然发生的事情,因为在此之前我做足了充分的准备工作,不单单是纯粹的刷题,更多的还会去刷一些Android核心架构进阶知识点,比如:JVM、高并发、多线程、缓存、热修复设计、插件化框架解读、组件化框架设计、图片加载框架、网络、设计模式、设计思想与代码质量优化、程序性能优化、开发效率优化、设计模式、负载均衡、算法、数据结构、高级UI晋升、Framework内核解析、Android组件内核等。

不仅有学习文档,视频+笔记提高学习效率,还能稳固你的知识,形成良好的系统的知识体系。这里,笔者分享一份从架构哲学的层面来剖析的视频及资料分享给大家梳理了多年的架构经验,筹备近6个月最新录制的,相信这份视频能给你带来不一样的启发、收获。

Android进阶学习资料库

一共十个专题,包括了Android进阶所有学习资料,Android进阶视频,Flutter,java基础,kotlin,NDK模块,计算机网络,数据结构与算法,微信小程序,面试题解析,framework源码!

大厂面试真题

PS:之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

《2017-2021字节跳动Android面试历年真题解析》

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

-i7XeVl0j-1712693952318)]

不仅有学习文档,视频+笔记提高学习效率,还能稳固你的知识,形成良好的系统的知识体系。这里,笔者分享一份从架构哲学的层面来剖析的视频及资料分享给大家梳理了多年的架构经验,筹备近6个月最新录制的,相信这份视频能给你带来不一样的启发、收获。

外链图片转存中...(img-2tm06LO3-1712693952318)

Android进阶学习资料库

一共十个专题,包括了Android进阶所有学习资料,Android进阶视频,Flutter,java基础,kotlin,NDK模块,计算机网络,数据结构与算法,微信小程序,面试题解析,framework源码!

外链图片转存中...(img-PGDWFhV5-1712693952318)

大厂面试真题

PS:之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

外链图片转存中...(img-raHbZlBf-1712693952319)

《2017-2021字节跳动Android面试历年真题解析》

外链图片转存中...(img-OcNyKHZ6-1712693952319)

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

外链图片转存中...(img-4lCnkK0G-1712693952319)

相关推荐
andr_gale22 分钟前
04_rc文件语法规则
android·framework·aosp
祖国的好青年1 小时前
VS Code 搭建 React Native 开发环境(Windows 实战指南)
android·windows·react native·react.js
黄林晴2 小时前
警惕!AGP 9.2 别只改版本号,R8 规则与构建链路全线收紧
android·gradle
小米渣的逆袭2 小时前
Android ADB 完全使用指南
android·adb
儿歌八万首2 小时前
Jetpack Compose Canvas 进阶:结合 animateFloatAsState 让自定义图形动起来
android·动画·compose
zhangphil3 小时前
Android Page 3 Flow读sql数据库媒体文件,Kotlin
android·kotlin
神探小白牙3 小时前
echarts,3d堆叠图
android·3d·echarts
李白的天不白4 小时前
如何项目发布到github上
android·vue.js
summerkissyou19874 小时前
Android-RTC、NTP 和 System Time(系统时间)
android