前言
本文转自一文搞懂Android JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧。
文章写得足够好,没必要班门弄斧,胡乱添加了。如果你感觉对你启发,欢迎去给他个关注。
Lifecycle、LiveData和ViewModel作为AAC架构的核心,常常被用在Android业务架构中。在京东商城Android应用中,为了事件传递等个性化需求,比如ViewModel间通信、ViewModel访问Activity等等,以及为了架构的扩展性,我们封装了BaseLiveData和BaseViewModel等基础组件,也对Activity、Fragement和ViewHolder进行了封装,以JDLifecycleBaseActivity、LifecycleBaseFragment和LifecycleBaseViewHolder等组件强化了View层功能,构建出了各业务线统一规范架构的基石。
在开发过程中,我们有时还会对它们的原理细节有些疑惑,比如会有Lifecycle会不会对性能造成影响、LiveData为什么是粘性事件的、ViewModel的生命周期是什么样的等等问题,这些问题或多或少会对我们的日常开发和协作造成影响,所以对这些组件的源码分析就变得很有必要,而掌握一些分析方法更能提高效率。本文就以Lifecycle、LiveData和ViewModel三大组件的源码分析为例,探讨一下分析方法和技巧,整体目录如下图所示,希望能给大家带来收获。
源码下载
以下关于androidx源码下载部分我会重新整理。这里的下载会因为墙国的原因应该是不可以的。
官方地址: https://android.googlesource.com/platform/frameworks/support/或Github: https://github.com/androidx/androidx,以上都列出了比较详细的下载步骤和编译方法,按步骤操作一般没多大问题,如果已经安装过repo工具,可以跳过第一步。
-
安装repo
mkdir ~/bin PATH=~/bin:$PATH curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo chmod a+x ~/bin/repo
-
配置git中的姓名和邮箱,已配置可忽略
git config --global user.name "Your Name" git config --global user.email "you@example.com"
-
创建一个文件夹存放要下载的源码
mkdir androidx-master-dev cd androidx-master-dev
-
使用repo命令下载源码仓库
repo init -u https://android.googlesource.com/platform/manifest -b androidx-master-dev repo sync -j8 -c
-
使用命令以Android Studio打开源码库
cd androidx-master-dev/frameworks/support/ ./studiow
第一次打开可能会自动下载一个最新的Android Studio,稍等一会儿,就可以看到熟悉的界面了。
如图,Lifecycle、LiveData和ViewModel三大组件的代码都在lifecycle包下。
组件介绍
为了对分析工作有个感性认识,先过一下各个组件的作用和简单用法。
本篇中可以去对照AAC-core-demo
demo理解Lifecycle、LiveData、ViewModel。
Lifecycle
Lifecycle可以方便我们处理Activity和Fragment的生命周期,可以将一些逻辑更加内聚和解耦,比如把资源的释放操作从Activity的回调代码中解耦出来,放到资源管理类中自动进行。该组件是后两个组件的基石,理解它的原理也有助于我们理解LiveData是如何保证不会造成内存泄漏的。
下面是一个简单的使用示例,在自定义LifecycleObserver的实现接口上,用注解的方式声明与生命周期相关联的方法。最后通过lifecycleOwner的getLifecycle()接口拿到Lifecycle管理类,并将定义LifecycleObserver的实现接口注册进去。LifecycleOwner通常是一个Activity或Fragment的实例。
MyObserver implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void connectListener() {
...
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void disconnectListener() {
...
}
}
lifecycleOwner.getLifecycle().addObserver(new MyObserver());
LiveData
LiveData是一个数据持有组件,主要用来通知数据观察者数据发生了更新,它通过与LifecycleOwner组件绑定,实现可以只在页面活跃状态下发起通知,并在页面销毁时自动取消订阅,防止内存泄漏。
下面的简单示例中,直接创建了一个MutableLiveData对象,他持有String类型的数据,通过它的observe()方法,将LifecycleOwner和监听者传入,实现感知生命周期并观察数据的功能。
MutableLiveData<String> liveString = new MutableLiveData<>();
liveString.observe(mOwner, new Observer<String>() {
@Override
public void onChanged(@Nullable final String s) {
Log.d(TAG, "onChanged() called with: s = [" + s + "]");
}
});
liveString.setValue("LiveData使用案例");
ViewModel
ViewModel是MVVM中的VM,被设计用来管理View依赖的数据,通常是持有LiveData和相关的处理逻辑。ViewModel管理的数据有一个特点,就是不会随着页面配置改变而销毁,但在页面销毁时则会正常跟着销毁。
下面的例子中,自定义了一个ViewModel,管理users这组数据,并且封装了加载users的处理逻辑。而View只需要监听users,在回调中根据users处理界面就好,这样就做到了界面和数据的分离。
public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers() {
if (users == null) {
users = new MutableLiveData<List<User>>();
loadUsers();
}
return users;
}
private void loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
组件关系
在实际的MVVM场景中,最常使用的是ViewModel和LiveData的API,比较通用的方式是ViewModel持有一个或多个LiveData,也就是需要我们开发者设计出这两个组件的聚合关系。而Lifecycle组件,则是在调用LiveData的addOberver()方法时用到的,这个方法需要传入一个LifecycleOwner对象,LifecycleOwner作为一个接口,是Lifecycle组件的重要组成部分。
通过分析组件的源码,可以从设计角度发现,Lifecycle组件的能力是LiveData和ViewModel实现的根本,LiveData的页面活跃状态下才发起通知、页面销毁时自动取消订阅,以及ViewModel销毁所管理的数据的特性,都是通过直接使用Lifecycle实现的,可以说Lifecycle是LiveData和ViewModel的重要组成部分。
源码分析方法
01自底向上
该方法是从使用细节出发,提出问题,再进入源码中探究答案,最后汇总出组件关系图,获得上层视角。在这里以自下向上的方法,分析一下LifeCycle的源码。
提出问题
首先,还是看这个使用示例:
MyObserver implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void connectListener() {
...
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void disconnectListener() {
...
}
}
lifecycleOwner.getLifecycle().addObserver(new MyObserver());
针对该示例所实现的作用,可以从输入、处理和输出这三个软件过程角度提出问题:1、Activity/Fragment的生命周期如何转化为不同类型的Lifecycle.Event?2、Lifecycle.Event经过哪些处理?3、如何分发到特定的LifecycleObserver实现?
探究答案
Activity/Fragment的生命周期如何转化为不同类型的Lifecycle.Event
先来看看第一个问题怎么在源码中找到答案,不过在这以前,不妨先简单猜测一下,最直接的想法是:直接在生命周期回调方法中创建对应类型的Event。在接下来的分析中,便可以着重于是不是这么实现的,如果更复杂,那么还有哪些是需要被特别考虑到的。
ComponentActiivty相关代码
public class ComponentActivity extends Activity implements LifecycleOwner, Component {
private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ReportFragment.injectIfNeededIn(this);
}
@CallSuper
protected void onSaveInstanceState(Bundle outState) {
Lifecycle lifecycle = this.getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
((LifecycleRegistry)lifecycle).setCurrentState(State.CREATED);
}
super.onSaveInstanceState(outState);
}
public Lifecycle getLifecycle() {
return this.mLifecycleRegistry;
}
}
从ComponentActiivty这个类中,可以看到它实现了LifecycleOwner接口,该类的子类也就有了提供Lifecycle的能力,除了LifecycleOwner的getLifecycle接口的实现,另外比较重要的就是ReportFragment.injectIfNeededIn(this)这条语句,以及它持有了一个Lifecycle的主要实现类LifecycleRegistry的示例。
ReportFragment的主要实现
public class ReportFragment extends Fragment {
private static final String REPORT_FRAGMENT_TAG = "android.arch.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();
}
}
//...
@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) {
Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
}
}
}
//...
}
静态方法injectIfNeededIn的主要作用就是为Activity提供Lifecycle能力,这里分成了两种情况,在Android 10及以上,Activity的源码修改成自己可以注册进LifecycleCallbacks监听器。而为了兼容旧版本,则需要Fragment的生命周期回调中进行分发,这也就是与最初推测相比特殊的地方,可以更加留意。不过这两种情况都是根据生命周期创建了Event枚举型,并最终都经过静态方法dispatch,调用了Lifecyce的handleLifecycleEvent方法。
Lifecycle.Event经过哪些处理
LifecycRegistry
public class LifecycleRegistry extends Lifecycle {
/**
* Custom list that keeps observers and can handle removals / additions during traversal.
*
* Invariant: at any moment of time for observer1 & observer2:
* if addition_order(observer1) < addition_order(observer2), then
* state(observer1) >= state(observer2),
*/
private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap = new FastSafeIterableMap<>();
private State mState;
private final WeakReference<LifecycleOwner> mLifecycleOwner;
public LifecycleRegistry(@NonNull LifecycleOwner provider) {
mLifecycleOwner = new WeakReference<>(provider);
mState = INITIALIZED;
}
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
State next = getStateAfter(event);
moveToState(next);
}
private void moveToState(State next) {
if (mState == next) {
return;
}
mState = next;
......
sync();
......
}
...
}
跟着源码可以定位到Lifecycle的实现类LifecycRegistry中,它主要是封装了对Lifecycle.Event的操作,包括了Lifecycle.Event与Lifecycle.State的同步,以及Lifecycle.State变化后通知观察者。
先来看handleLifecycleEnvent的实现,通过传进来的event获取一个state枚举值,具体的实现代码如下: