Activity启动流程源码分析(旧版)

QuibblerQuibbler 2020-04-18 约 13 分钟 1933 次阅读

Activity启动流程源码分析(旧版)

2020年4月19号,周末两天把Activity启动的源码流程捋一遍。Android源码确实太“跳”了,如果对Android整体源码的框架没有整体的概念,可能很容易读着读着“跟丢”代码。

重新装上Visio,一遍看源码,一遍捋逻辑图。对代码阅读能力确实有很大提升,想到去年刚进项目的时候,先统计了一下模块的代码,大概十万行,这得看到什么时候啊!其实不需要全部都看,对主要的流程都了解,还有就是平时经常接触修改的代码,在纸上画流程图,刚开始很吃力,也是会“跟丢”代码,后来对整体的逻辑熟悉了能很快定位代码。


2021年3月3号更新,阅读API 30的源码分析Activity的启动流程,见Activity启动流程全新版本(基于API 30)。



1、从startActivity开始

调用startActivity()传入Intent参数启动Activity,再熟悉不过的用法:

startActivity(intent);

顺着这个方法,Activity内部经过各种重载函数的跳转调用

public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

最终是调用的startActivityForResult()方法,其中一行代码:

Instrumentation.ActivityResult ar =mInstrumentation.execStartActivity(this,
                                       mMainThread.getApplicationThread(), 
                                       mToken, this,intent, requestCode, options);

2、通过Instrumentation对接AMS

直接到了Instrumentation类,调用execStartActivity(...)方法,方法中:

int result = ActivityTaskManager.getService()
    	        .startActivity(whoThread, who.getBasePackageName(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()),
                token, target != null ? target.mEmbeddedID : null,
                requestCode, 0, null, options);

之前的Android源码是ActivityManager,新版本的API已经做了很大的改动,改成了ActivityTaskManager,花了很多时间才捋清,后面继续看。

ActivityTaskManager的getService()方法返回单例模板类构造的IActivityTaskManager单例。

3、ATMS服务

IActivityTaskManager是AIDL接口,真正的实现在系统服务层的ActivityTaskManagerService。注意因为源码已经做了很大的改动,所以这里不是还像之前各种博客和书籍上说的用AMS服务:ActivityManagerService。

ActivityTaskManagerService中调用链:startActivity -> startActivityAsUser方法中:

return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
        .setCaller(caller)
        .setCallingPackage(callingPackage)
        .setResolvedType(resolvedType)
        .setResultTo(resultTo)
        .setResultWho(resultWho)
        .setRequestCode(requestCode)
        .setStartFlags(startFlags)
        .setProfilerInfo(profilerInfo)
        .setActivityOptions(bOptions)
        .setMayWait(userId)
        .execute();

3.1、控制器:ActivityStartController

ActivityStartController类是新增的,用来控制Activity的启动,通过ActivityStartController获取ActivityStarter。


3.2、启动器:ActivityStarter

        ActivityStarter设置大量参数,最后调用execute()方法开始漫长的启动流程。

int execute() {
        try {
            if (mRequest.mayWait) {
                return startActivityMayWait(...);
            } else {
                return startActivity(....);
            }
        } finally {
            onExecutionComplete();
        }
    }

这里由于前面调用setMayWait(userId)方法,所以mRequest.mayWait一直为true。值得一提的是Request是的静态内部类,作用就是记录一些请求信息。

3.3、漫长的调用链

在ActivityStarter类中经过漫长的调用链:startActivityMayWait->startActivity->startActivity->...->startActivityUnchecked,ActivityStarter的任务快完成了。

ActivityStack类中调用链:从resumeTopActivityUncheckedLocked->resumeTopActivityInnerLocked->topRunningActivityLocked

ActivityStackSupervisor类中调用链:startSpecificActivityLocked->realStartActivityLocked->ClientLifecycleManager#scheduleTransaction。在这里的startSpecificActivityLocked方法中,如果启动Activity所在APP的进程没有启动,还会先执行启动APP的进程,见APP进程启动。

ClientTransaction中的getClient()方法获取IApplicationThread

4、应用进程ActivityThread

ApplicationThread实现了IApplicationThreadAIDL接口。ApplicationThread是ActivityThread的内部类,ActivityThread同时也继承了ClientTransactionHandler抽象类,实现sendMessage()方法,这个方法正是在ClientTransaction.schedule()中调用的,schedule()被上面的ClientLifecycleManager#scheduleTransaction调用。

4.1、attach()完成Activity的初始化

在performLaunchActivity()方法中使用下面这个方法创建Activity:

newActivity(Class<?> clazz, Context context, 
            IBinder token, Application application, Intent intent, ActivityInfo info, 
            CharSequence title, Activity parent, String id,
            Object lastNonConfigurationInstance)

创建后会调用Activity的attach()方法,传入ContextImpl,就是mBase。在ActivityThread的performLaunchActivity中获取到Activity实例后再调用Activity的attach()方法:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
        ... ...
        activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback,
                        r.assistToken);
        ... ...
    }


4.2、回调onCreate()

从一开始启动Activity方法最终经过静态内部Handler类H的各种消息传递、中转调用。最后又回到了ActivityThread类中的handleLaunchActivity方法,经过调用链:handleLaunchActivity->callActivityOnCreate->performCreate->onCreate。完成Activity的加载,启动,调用Activity的onCreate()方法。

推荐阅读:

        庖丁解牛 Activity 启动流程

        Activity启动过程源码分析

        Android的Activity启动流程分析

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w