媳妇看了都说好!Android JetPack组件原理之Lifecycle、LiveData、ViewModel与源码分析技巧

前言

Lifecycle、LiveData和ViewModel作为AAC架构的核心,常常被用在Android业务架构中。在京东商城Android应用中,为了事件传递等个性化需求,比如ViewModel间通信、ViewModel访问Activity等等,以及为了架构的扩展性,我们封装了BaseLiveData和BaseViewModel等基础组件,也对Activity、Fragement和ViewHolder进行了封装,以JDLifecycleBaseActivity、LifecycleBaseFragment和LifecycleBaseViewHolder等组件强化了View层功能,构建出了各业务线统一规范架构的基石。

纸上说来终觉浅,时间比较充裕的小伙伴建议去B站观看第三方库系列视频讲解:Android第三方开源库系列
Jetpack组件全家桶视频讲解:Android第三方开源库系列—Jetpack全家桶(已完结)

在开发过程中,我们有时还会对它们的原理细节有些疑惑,比如会有Lifecycle会不会对性能造成影响、LiveData为什么是粘性事件的、ViewModel的生命周期是什么样的等等问题,这些问题或多或少会对我们的日常开发和协作造成影响,所以对这些组件的源码分析就变得很有必要,而掌握一些分析方法更能提高效率。本文就以Lifecycle、LiveData和ViewModel三大组件的源码分析为例,探讨一下分析方法和技巧,整体目录如下图所示,希望能给大家带来收获。

源码下载

官方地址: https://android.googlesource.com/platform/frameworks/support/或Github: https://github.com/androidx/androidx,以上都列出了比较详细的下载步骤和编译方法,按步骤操作一般没多大问题,如果已经安装过repo工具,可以跳过第一步

1. 安装repo

mkdir ~/bin

PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo

2. 配置git中的姓名和邮箱,已配置可忽略

git config --global user.name "Your Name"

git config --global user.email "you@example.com"pet__string">"you@example.com"

3. 创建一个文件夹存放要下载的源码

mkdir androidx-master-dev
cd androidx-master-dev

4. 使用repo命令下载源码仓库

repo init -u https://android.googlesource.com/platform/manifest -b androidx-master-dev
repo sync -j8 -c

5. 使用命令以Android Studio打开源码库

cd androidx-master-dev/frameworks/support/
./studiow

第一次打开可能会自动下载一个最新的Android Studio,稍等一会儿,就可以看到熟悉的界面了。

如图,Lifecycle、LiveData和ViewModel三大组件的代码都在lifecycle包下。

组件介绍

为了对分析工作有个感性认识,先过一下各个组件的作用和简单用法。

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 moveToStat
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值