基于android10.0源码分析Activity的启动流程

一、梳理源码流程干什么

Activity是四大组件中最重要的组件之一,下面来分析Activity的启动过程,了解Activity的启动过程能帮助我们更好的对组件Activity的理解,也能帮助我们更好的把控Activity生命周期的变化过程。

当然Activity作为四大组件之首,10.0版本的Activity的代码函数在8000行,关联的一些类Instrumentation、ActivityTaskManager、ActivityStarter等等,怎么也是几万行的代码,一次完全分析起来会很困难,这里面主要通过启动的核心流程源码分析,帮我们理清楚Activity的启动流程,内部其实有很多细节,这些细节和我们的日常开发也都非常相关,关于这部分细节性的代码,由于篇幅问题,本文并不会全部体现。

先上Activity启动流程梳理图:

上图非完整的启动流程,在后续源码分析中,还有第二条分支,就是当application未创建的情况下,会去创建进程,fork应用进程等,后文的源码分析中会简单提到,详细流程也适合做专题分析。

通过这样的一个梳理图,主要是清晰系统进程和应用进程中的代码调用流程,建议先初步看一下梳理图,在看后面的源码分析过程中不断的回到图中来,加深自己的理解和印象,在文章末尾,源码分析之后,也会对梳理图中的核心类进行说明。

二、源码流程分析

下面主要从源码角度来进行分析,分析的入口就是startActivity(),分析源码中的Activity.java中的startActivity()方法

2.1 应用进程StartActivity

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

从上述代码来看startActivity的方法体来看,最终都会调用startActivityForResult()方法,接下来看startActivityForResult方法源码:

 public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
   
        if (mParent == null) {
   //标注1
            options = transferSpringboardActivityOptions(options);
            //标注2
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
   
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
   
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
   //标注3
            if (options != null) {
   
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
   
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

在startActivityForResult方法体中,先看到了标注1的位置是一个条件判断mParent==null。mParent代表的是ActivityGroup,Api13已经被废弃,这里面其实我们标注3的内容就不用太多去关注了,当然从方法名上mParent.startActivityFromChild也能看出来,的确是子Activity来启动Activity。我们把关注点仍然回到标注2的位置

mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);

mInstumentation好像很面熟,当然这个类比我们想象的要强大的多,Instrumentation为仪表盘,管理着Activity和Application的生命周期,一个进程对应了一个Instrumentation。

在后续的分析过程中,我们会看到Instrumentation在整个Activity启动过程中的强大作用,接下来我们继续分析execStartActivity的核心流程

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
   
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        省去非核心流程代码...
        try {
   
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            //这块的代码和8.0的是有区别,这块也是我们启动流程里面的核心代码
            //8.0里面的源码:ActivityManagerNative.getDefault()
            int result = ActivityTaskManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
   
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

上述标注1的位置,可以看到启动activity的真正实现交给了ActivityTaskManager.getService()的startActivity的方法了。

 public static IActivityTaskManager getService() {
   
        return IActivityTaskManagerSingleton.get();
    }
 private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
            new Singleton<IActivityTaskManager>() {
   
                @Override
                protected IActivityTaskManager create() {
   
                  //获得Binder对象实例
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
                    return IActivityTaskManager.Stub.asInterface(b);
                }
            };

从这里可以推测,此处把application启动的过程要转交给通过ActivityTaskManager获得IActivityTaskManagerSingleton的单例对象去处理,上述备注部分,可以看出返回的是一个Aidl的接口实例。

我们也查看IActivityTaskManager的实现类,通过源码我们找到了ActivityTaskManagerService继承了IActivityTaskManager。

public class ActivityTaskManagerService extends IActivityTaskManager.Stub{
   ...省去...}

从这里,也可以印证:同一个应用A activity启动一个B activity 本质上也是一个跨进程调用的过程。

为什么这里面需要用AMS的Binder对象呢?

看到Binder,有些android知识储备的应该能想到这是跨进程通信,那么到底哪两个进程进行了跨进程的通信?这里面需要了解到ActivityManagerService实际上是在android系统启动的时候,这个服务就被开启了,这个服务被运行在系统进程中,即ActivityMangerService是运行在android system进程中的,并且系统一启动,这个service就会被启动。这里面显然是我们自己的app进程和system进程之间进行了ipc调用。

2.2进入到ATMS进程startActivity

ATMS,即ActivityTaskServiceManager,运行在系统服务进程中,继续看ActivityTaskManagerService中的源码:

@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
   
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}

实际会调用startActivityAsUser()。startActvityAsUser()的实现:

int startActivityAsUser(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
        boolean validateIncomingUser) {
   
    ...
    // TODO: Switch to user app stacks here.
    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();//实际调用的是ActivityStarter的excute的方法

}

execute的方法实际ActivityStarter类在执行,之后再调用到startActivityUnchecked(),再调用到RootActivityContainer类中resumeFocusedStacksTopActivities(),最终会调用到ActivityStack的resumeTopActivityUncheckdeLocked(),RootActivityContainer类中的代码调用如下

if (!resumedOnDisplay) {
   
    // 查找符合条件的任务栈
    final ActivityStack focusedStack = display.getFocusedStack();
    if (focusedStack != null) {
   
        focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
}

ActivityStack中的resumeTopActivityUncheckedLocked()的源码:

/**
 * 确定栈顶Activity是否是resumed
 */
@GuardedBy("mService")
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
   
    if (mInResumeTopActivity) {
   
        // Don't even start recursing.
        return false;
    }
    boolean result = false;
    try {
   
        mInResumeTopActivity = true;
        //核心代码:
        result = resumeTopActivityInnerLocked(prev, options);
        // 栈顶有resuming的activity,有必要进行pause 
        final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
        if (next == null || 
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hymKing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值