Android Jetpack架构组件(三)Lifecycle原理篇
程序员文章站
2022-06-10 14:49:08
...
前言
上一篇讲述了Jetpack中的Lifecycle的使用,这一篇我们从源码角度来分析一下它是如何实现的。
源码解析(基于最新的lifecycle2.2.0版本)
- 在上一篇的Lifecycle使用篇中我们知道了怎么使用,这里我们把源码部分贴出来,我们从使用的角度来分析源码是如何实现的:
class DetailActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_app_detail) //-----1----- lifecycle.addObserver(LifecycleListener()) } override fun onStart() { super.onStart() Log.i("aaa", "Activity onStart ") } override fun onStop() { super.onStop() Log.i("aaa", "Activity onStop ") } //-----2----- class LifecycleListener : LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_START) fun onStart() { Log.i("aaa", "listener onStart ") } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) fun onStop() { Log.i("aaa", "listener onStop ") } }
- 首先在注释2处,我们声明了一个
LifecycleListener
,然后在注释1处调用lifecycle.addObserver
将LifecycleListener()
传进去(Fragment同理
),我们就从这里的开始源码的分析。但是在分析源码之前,我们先大致捋一下Lifecycle的原理和继承结构,Lifecycle是一种观察者模式,在Activity中持有LifecycleObserver
的实现类,然后根据生命周期的变化,调用对应的LifecycleObserver
中的方法来实现逻辑代码。 - 针对源码结构部分,我们先来看一下, 心中大概有个印象,后面用到的时候会详细讲解 :
public interface LifecycleObserver { } public interface LifecycleEventObserver extends LifecycleObserver { void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event); } class ReflectiveGenericLifecycleObserver implements LifecycleEventObserver { private final Object mWrapped; private final CallbackInfo mInfo; ReflectiveGenericLifecycleObserver(Object wrapped) { mWrapped = wrapped; mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass()); } @Override public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Event event) { mInfo.invokeCallbacks(source, event, mWrapped); } } public interface LifecycleOwner { Lifecycle getLifecycle(); } public abstract class Lifecycle { @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) @NonNull AtomicReference<Object> mInternalScopeRef = new AtomicReference<>(); @MainThread public abstract void addObserver(@NonNull LifecycleObserver observer); @MainThread public abstract void removeObserver(@NonNull LifecycleObserver observer); @MainThread @NonNull public abstract State getCurrentState(); @SuppressWarnings("WeakerAccess") public enum Event { ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY, ON_ANY } @SuppressWarnings("WeakerAccess") public enum State { DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED; public boolean isAtLeast(@NonNull State state) { return compareTo(state) >= 0; } } } public class LifecycleRegistry extends Lifecycle { ... }
- 好了,下面我们开始从Activity的
getLifecycle()
开始分析,这个方法是在ComponentActivity
中的,源码如下所示:class ComponentActivity implements LifecycleOwner private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this); public Lifecycle getLifecycle() { return mLifecycleRegistry; } }
- 上面
LifecycleRegistry
是Lifecycle
的唯一的实现类,看名字就知道它是负责对LifecycleObserver
的注册和解除注册的操作。接着我们看addObserver(observer)
源码:@Override public void addObserver(@NonNull LifecycleObserver observer) { State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED; ObserverWithState statefulObserver = new ObserverWithState(observer, initialState); ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver); if (previous != null) { return; } LifecycleOwner lifecycleOwner = mLifecycleOwner.get(); if (lifecycleOwner == null) { // it is null we should be destroyed. Fallback quickly return; } boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent; State targetState = calculateTargetState(observer); mAddingObserverCounter++; while ((statefulObserver.mState.compareTo(targetState) < 0 && mObserverMap.contains(observer))) { pushParentState(statefulObserver.mState); statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState)); popParentState(); // mState / subling may have been changed recalculate targetState = calculateTargetState(observer); } if (!isReentrance) { // we do sync only on the top level. sync(); } mAddingObserverCounter--; } static class ObserverWithState { State mState; LifecycleEventObserver mLifecycleObserver; ObserverWithState(LifecycleObserver observer, State initialState) { mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer); mState = initialState; } void dispatchEvent(LifecycleOwner owner, Event event) { State newState = getStateAfter(event); mState = min(mState, newState); mLifecycleObserver.onStateChanged(owner, event); mState = newState; } }
- 在
addObserver
方法的开头先将mState
赋值为INITIALIZED
状态,然后将传入的实参observer
用ObserverWithState
包装起来,ObserverWithState
中仅仅存在两个变量,一个是State, 一个是LifecycleEventObserver
。然后将封装类放在mObserverMap
这个map中,便于将来取出来使用。addObserver
方法中后面的代码因为是第一次调用addObserver
,所以后面的代码就没什么实际的作用,就不分析了。接着我们看自定义的LifecycleListener
中的方法是如何跟随生命周期被调用的。 - 我们看下
ComponentActivity
的onCreate
方法源码:@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mSavedStateRegistryController.performRestore(savedInstanceState); ReportFragment.injectIfNeededIn(this); if (mContentLayoutId != 0) { setContentView(mContentLayoutId); } }
- 我们看到其中调用了
ReportFragment.injectIfNeededIn(this)
,其中ReportFragment
是一个分发生命周期事件的类,它是一个没有界面的Fragment.它的主要作用就是用来监控生命周期的变化并做相应的响应。我们看下ReportFragment
整个源码:@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class ReportFragment extends Fragment { private static final String REPORT_FRAGMENT_TAG = "androidx.lifecycle" + ".LifecycleDispatcher.report_fragment_tag"; public static void injectIfNeededIn(Activity activity) { if (Build.VERSION.SDK_INT >= 29) { // On API 29+, we can register for the correct Lifecycle callbacks directly activity.registerActivityLifecycleCallbacks( new LifecycleCallbacks()); } // Prior to API 29 and to maintain compatibility with older versions of // ProcessLifecycleOwner (which may not be updated when lifecycle-runtime is updated and // need to support activities that don't extend from FragmentActivity from support lib), // use a framework fragment to get the correct timing of Lifecycle events android.app.FragmentManager manager = activity.getFragmentManager(); if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) { manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit(); // Hopefully, we are the first to make a transaction. manager.executePendingTransactions(); } } @SuppressWarnings("deprecation") static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) { if (activity instanceof LifecycleRegistryOwner) { ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event); return; } if (activity instanceof LifecycleOwner) { Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle(); if (lifecycle instanceof LifecycleRegistry) { ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event); } } } static ReportFragment get(Activity activity) { return (ReportFragment) activity.getFragmentManager().findFragmentByTag( REPORT_FRAGMENT_TAG); } private ActivityInitializationListener mProcessListener; private void dispatchCreate(ActivityInitializationListener listener) { if (listener != null) { listener.onCreate(); } } private void dispatchStart(ActivityInitializationListener listener) { if (listener != null) { listener.onStart(); } } private void dispatchResume(ActivityInitializationListener listener) { if (listener != null) { listener.onResume(); } } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); dispatchCreate(mProcessListener); dispatch(Lifecycle.Event.ON_CREATE); } @Override public void onStart() { super.onStart(); dispatchStart(mProcessListener); dispatch(Lifecycle.Event.ON_START); } @Override public void onResume() { super.onResume(); dispatchResume(mProcessListener); dispatch(Lifecycle.Event.ON_RESUME); } @Override public void onPause() { super.onPause(); dispatch(Lifecycle.Event.ON_PAUSE); } @Override public void onStop() { super.onStop(); dispatch(Lifecycle.Event.ON_STOP); } @Override public void onDestroy() { super.onDestroy(); dispatch(Lifecycle.Event.ON_DESTROY); // just want to be sure that we won't leak reference to an activity mProcessListener = null; } private void dispatch(@NonNull Lifecycle.Event event) { if (Build.VERSION.SDK_INT < 29) { // Only dispatch events from ReportFragment on API levels prior // to API 29. On API 29+, this is handled by the ActivityLifecycleCallbacks // added in ReportFragment.injectIfNeededIn dispatch(getActivity(), event); } } void setProcessListener(ActivityInitializationListener processListener) { mProcessListener = processListener; } interface ActivityInitializationListener { void onCreate(); void onStart(); void onResume(); } }
- 从上面的
injectIfNeededIn
源码部分看到,在Android 29以上直接通过activity.registerActivityLifecycleCallbacks
来注册的,我们关注下面的injectIfNeededIn
方法内部底部的内容,它会将ReportFragment
添加到FragmentManager
中。 - 然后我们来关注生命周期部分,我们看到每一个生命周期都会对应的调用
dispatch
方法,从而触发后续的操作,我们以onStart
源码为例进行分析:@Override public void onStart() { super.onStart(); dispatchStart(mProcessListener); dispatch(Lifecycle.Event.ON_START); } private void dispatch(@NonNull Lifecycle.Event event) { if (Build.VERSION.SDK_INT < 29) { // Only dispatch events from ReportFragment on API levels prior // to API 29. On API 29+, this is handled by the ActivityLifecycleCallbacks // added in ReportFragment.injectIfNeededIn dispatch(getActivity(), event); } } static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) { if (activity instanceof LifecycleRegistryOwner) { ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event); return; } if (activity instanceof LifecycleOwner) { //-----1----- Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle(); if (lifecycle instanceof LifecycleRegistry) { ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event); } } }
- 因为Component是实现的
LifecycleOwner
, 所以接着会进入到注释1的判断中,然后调用handleLifecycleEvent
, 我们看源码部分, 首先会调用getStateAfter
:public void handleLifecycleEvent(@NonNull Lifecycle.Event event) { State next = getStateAfter(event); moveToState(next); } static State getStateAfter(Event event) { switch (event) { case ON_CREATE: case ON_STOP: return CREATED; case ON_START: case ON_PAUSE: return STARTED; case ON_RESUME: return RESUMED; case ON_DESTROY: return DESTROYED; case ON_ANY: break; } throw new IllegalArgumentException("Unexpected event value " + event); }
-
getStateAfter
的逻辑可以用一张图来解释说明一下, 这里Event
代表的是事件,基本包含了重要的生命周期,getStateAfter
转换为对应的State
,只包含了INITIALIZED
,CREATED
,STARTED
,RESUMED
,以及DESTROYED
。
- 通过
getStateAfter
得到的是State为STARTED
, 接着会调用moveToState(state)
方法:private void moveToState(State next) { if (mState == next) { return; } mState = next; if (mHandlingEvent || mAddingObserverCounter != 0) { mNewEventOccurred = true; // we will figure out what to do on upper level. return; } mHandlingEvent = true; sync(); mHandlingEvent = false; }
- moveToState首先判断mState状态是否和传进来的一样,如果是的话就return, 我们接下来看
sync()
方法:private void sync() { LifecycleOwner lifecycleOwner = mLifecycleOwner.get(); if (lifecycleOwner == null) { throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already" + "garbage collected. It is too late to change lifecycle state."); } while (!isSynced()) { mNewEventOccurred = false; // no need to check eldest for nullability, because isSynced does it for us. //-----1----- if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) { backwardPass(lifecycleOwner); } Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest(); if (!mNewEventOccurred && newest != null //-----2----- && mState.compareTo(newest.getValue().mState) > 0) { forwardPass(lifecycleOwner); } } mNewEventOccurred = false; }
-
sync()
在注释1处首先判断当前状态mState
和mObserverMap.eldest().getValue().mState
的的关系,如果mState
状态在它之前就调用backwardPass
,如果在它之后就调用注释2处的forwardPass
,这里满足注释2处的条件,就以forwardPass
为例,其实和backwardPass
大同小异:private void forwardPass(LifecycleOwner lifecycleOwner) { Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator = mObserverMap.iteratorWithAdditions(); while (ascendingIterator.hasNext() && !mNewEventOccurred) { Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next(); ObserverWithState observer = entry.getValue(); while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred && mObserverMap.contains(entry.getKey()))) { pushParentState(observer.mState); //-----1----- observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState)); popParentState(); } } }
- 调用了
observer.dispatchEvent
方法:static class ObserverWithState { State mState; LifecycleEventObserver mLifecycleObserver; ObserverWithState(LifecycleObserver observer, State initialState) { //----1----- mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer); mState = initialState; } void dispatchEvent(LifecycleOwner owner, Event event) { State newState = getStateAfter(event); mState = min(mState, newState); //-----2----- mLifecycleObserver.onStateChanged(owner, event); mState = newState; } }
- 注释1处
ObserverWithState
的构造方法在addObserver
时候被调用,ObserverWithState
中有一个变量mLifecycleObserver通过Lifecycling.lifecycleEventObserver(observer)
得到,查看源码得知mLifecycleObserver这里是ReflectiveGenericLifecycleObserver
对象,所以在注释2处实际上调用的是ReflectiveGenericLifecycleObserver.onStateChanged
方法,源码如下:class ReflectiveGenericLifecycleObserver implements LifecycleEventObserver { private final Object mWrapped; private final CallbackInfo mInfo; ReflectiveGenericLifecycleObserver(Object wrapped) { mWrapped = wrapped; //-----1----- mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass()); } @Override public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Event event) { //-----2----- mInfo.invokeCallbacks(source, event, mWrapped); } }
- 在调用注释2处代码之前,我们先分析
mInfo
是做什么的,以及它是怎么来的。在构造方法中通过传入的wrapped
参数获取mInfo
,这里wrapped
就是我们前面自定义的LifecycleObserver
对象,我们先看注释1处的getInfo
方法。private final Map<Class<?>, CallbackInfo> mCallbackMap = new HashMap<>(); CallbackInfo getInfo(Class<?> klass) { CallbackInfo existing = mCallbackMap.get(klass); if (existing != null) { return existing; } existing = createInfo(klass, null); return existing; }
- 在getInfo中先尝试从
mCallbackMap
中获取,如果为空的话再走createInfo()方法来获取CallbackInfo
,下面是createInfo
源码:private CallbackInfo createInfo(Class<?> klass, @Nullable Method[] declaredMethods) { //-----1----- Class<?> superclass = klass.getSuperclass(); //-----2----- Map<MethodReference, Lifecycle.Event> handlerToEvent = new HashMap<>(); if (superclass != null) { CallbackInfo superInfo = getInfo(superclass); if (superInfo != null) { handlerToEvent.putAll(superInfo.mHandlerToEvent); } } //-----3----- Class<?>[] interfaces = klass.getInterfaces(); for (Class<?> intrfc : interfaces) { for (Map.Entry<MethodReference, Lifecycle.Event> entry : getInfo( intrfc).mHandlerToEvent.entrySet()) { verifyAndPutHandler(handlerToEvent, entry.getKey(), entry.getValue(), klass); } } //-----4----- Method[] methods = declaredMethods != null ? declaredMethods : getDeclaredMethods(klass); boolean hasLifecycleMethods = false; for (Method method : methods) { //-----5----- OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class); if (annotation == null) { continue; } hasLifecycleMethods = true; //-----6----- Class<?>[] params = method.getParameterTypes(); int callType = CALL_TYPE_NO_ARG; if (params.length > 0) { callType = CALL_TYPE_PROVIDER; if (!params[0].isAssignableFrom(LifecycleOwner.class)) { throw new IllegalArgumentException( "invalid parameter type. Must be one and instanceof LifecycleOwner"); } } Lifecycle.Event event = annotation.value(); //------7------ if (params.length > 1) { callType = CALL_TYPE_PROVIDER_WITH_EVENT; if (!params[1].isAssignableFrom(Lifecycle.Event.class)) { throw new IllegalArgumentException( "invalid parameter type. second arg must be an event"); } if (event != Lifecycle.Event.ON_ANY) { throw new IllegalArgumentException( "Second arg is supported only for ON_ANY value"); } } //-----8----- if (params.length > 2) { throw new IllegalArgumentException("cannot have more than 2 params"); } //-----9----- MethodReference methodReference = new MethodReference(callType, method); //-----10----- verifyAndPutHandler(handlerToEvent, methodReference, event, klass); } //-----11----- CallbackInfo info = new CallbackInfo(handlerToEvent); mCallbackMap.put(klass, info); mHasLifecycleMethods.put(klass, hasLifecycleMethods); return info; }
- 首先在注释1处获取待处理的类的父类,看父类中是否有和生命周期相关的方法加入到注释2创建的Map中,这个Map是以Key为
MethodReference
,Value为Lifecycle.Event
, 其中MethodReference
是封装了Method的一个类。注释3处是处理接口相关的信息。 - 注释4处会通过
getDeclaredMethods
拿到所有在这个类中声明的方法,包括public, protected,private修饰符修饰的方法,但是不包括继承的方法以及接口中default修饰的方法,这个和getMethods(只能获取到public声明的方法,包括public修饰的继承的方法以及接口中的default方法)
要注意区别。 - 获取到方法之后就进入了
for
循环,会在注释5处获取方法的OnLifecycleEvent
注解,如果注解为空的话就直接continue进入下一个元素。 - 注释6处获取这个方法参数的类型,
callType
有三种取值,其中默认情况下等于CALL_TYPE_NO_ARG
, 如果参数的长度大于0的话就将callType
赋值为CALL_TYPE_PROVIDER
,并且使用isAssignableFrom
来检测第一个参数是不是属于LifecycleOwner
, 如果不是的话就要抛出异常。 - 注释7处会获取注解的值,接下来会判断如果参数的数量大于1的话就将
callType
赋值为CALL_TYPE_PROVIDER_WITH_EVENT
, 并且如果第二个参数不是ON_ANY
的话,也会抛出异常。 - 注释8处判断参数的长度不能大于两个,如果大于两个的话还是会抛出异常。
- 注释9处会将上面的
callType
和method
封装到MethodReference
中,然后在注释10处将methodReference
和event
放入前面注释2的handlerToEvent
中。 - 注释11处创建我们需要的
callbackInfo
,然后将其放入mCallbackMap
中,最后返回生成的callbackInfo
。 - 综上分析,如果我们想使用注解的方法带有参数的话,如果是一个参数的话,这个参数一定要是
LifecycleOwner
类型的;如果是两个参数的话,第一个参数还得是LifecycleOwner
类型,而且第二个参数必须得是Lifecycle.Event
类型的,并且注解中的事件必须是ON_ANY
;如果大于两个参数的也是会抛出异常的。
- 首先在注释1处获取待处理的类的父类,看父类中是否有和生命周期相关的方法加入到注释2创建的Map中,这个Map是以Key为
- 然后再分析前面
ReflectiveGenericLifecycleObserver
中的onStateChanged
方法,它调用的是mInfo.invokeCallbacks(source, event, mWrapped);
方法,我们看一下整个类的源码,源码如下:static class CallbackInfo { final Map<Lifecycle.Event, List<MethodReference>> mEventToHandlers; final Map<MethodReference, Lifecycle.Event> mHandlerToEvent; //-----1----- 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<MethodReference> methodReferences = mEventToHandlers.get(event); if (methodReferences == null) { methodReferences = new ArrayList<>(); mEventToHandlers.put(event, methodReferences); } methodReferences.add(entry.getKey()); } } @SuppressWarnings("ConstantConditions") //-----2----- 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<MethodReference> handlers, LifecycleOwner source, Lifecycle.Event event, Object mWrapped) { if (handlers != null) { for (int i = handlers.size() - 1; i >= 0; i--) { //-----3----- handlers.get(i).invokeCallback(source, event, mWrapped); } } } }
- 我们看到
invokeCallbacks
中出现了mEventToHandlers
变量,这个变量其实是在注释1 处CallbackInfo
的构造方法中将我们刚才在createInfo
中遍历得到的mHandlerToEvent
的Key和Value交换位置,存储到了mEventToHandlers
, 这是为了方便后续的根据Event得到对应的MethodReference
列表的操作。 - 然后进入到了注释2的
invokeCallbacks
中,代码执行了invokeMethodsForEvent
。mEventToHandlers.get(event)
获取的是Event
对应的MethodReference
列表,注释3处是对此列表进行遍历,然后执行MethodReference
中的invokeCallback
方法,源码如下:
static 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); } }
- 然后根据前面分析的
callType
来反射调用,最终达到了我们需要的效果。 - 整个流程可以用一张图来只管感受一下:
- 我们看到
总结
其实Lifecycle的源码也不算太多,理解起来也不算太慢,简单来说就是我们自定义的LifecycleObserver
中使用注解修饰的方法以及事件都会在addObserver
时候被保存起来,在生命周期发生变化的时候,通过反射找到对应的方法执行调用即可。如果对Lifecycle使用不熟悉的,可以参考Lifecycle使用篇。
推荐阅读
-
Android Jetpack架构组件之Lifecycle
-
阿里巴巴内部Jetpack宝典意外流出!极致经典,堪称Android架构组件的天花板
-
Android 架构组件之 LifeCycle详解
-
Android Jetpack 架构开发组件化应用实战
-
Android Jetpack架构开发组件化应用实战
-
Android Jetpack架构开发组件化应用实战
-
Android Jetpack架构开发组件化应用实战
-
Android Jetpack架构组件(六)一文带你了解ViewModel的使用和原理
-
Android Jetpack架构组件(三)一文带你了解Lifecycle(原理篇)
-
Android Jetpack(三)LiveData 组件原理剖析