Android Activity启动(三) 首次启动App时,activity跳转过程及原理解析

      在开始本文之前,要提一些相对偏一点的知识点,我们所看到的手机桌面Launcher,也是继承于Activity,当我们安装完一个其他的应用程序之后,就会在桌面Launcher上生成一个对应的应用程序的图标,首次点击这个图标的时候,Launcher就会启动该图标对应应用程序的首页Activty,一般启动的都是我们工程中的MainActivity,其实这个过程走的是一个Activity的启动的流程,与在App内部启动一个Activity的不同之处在于,点击桌面Launcher首次启动一个应用程序的时候,会先去创建一个该应用程序对应的进程,然后执行ActivityThread的main()方法去创建该应用对应的Application,然后再去启动首页Activity。在这整个过程中,Application的创建过程,以及Activity的大部分的启动过程已经在Android Activity启动(一),Application创建的过程以及原理分析和 Android Activity启动(二)App内部activity跳转过程及原理分析这前两篇博客中讲到了。

      首次启动app时,Activity的跳转流程与在App内部启动一个Activity的流程,在前半部分是基本一致的,所以Activity启动的前半部分我不打算再描述一遍了,只从ActivityStackSupervisor类中的startSpecificActivityLocked()方法开始讲起,因为在这个方法中区分了到底是该去创建一个应用程序对应的进程,还是直接去启动一个Activity,关于开始启动一个Activity直到调用ActivityStackSupervisor的startSpecificActivityLocked()方法的这个前半部分的启动过程,有还不是很理解的同学可以先看下我的上一篇博客Android Activity启动(二)App内部activity跳转过程及原理分析,上篇博客已经讲的很详细了。本篇博客,我们从ActivityStackSupervisor的startSpecificActivityLocked()开始说起,下面我们来看下代码

void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
    //获取该Activity对应的进程对象
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);

    r.getStack().setLaunchTime(r);

    /*
     * 因为我们本篇博客讲解的是App内部Activity的跳转过程
     * 所以该Activity对应的进程对象肯定存在
     * 下面的if语句里面的判断条件肯定会成立  
     */     
    if (app != null && app.thread != null) {
        try {
           ......
           //启动新的Activity
           realStartActivityLocked(r, app, andResume, checkConfig);
           return;
          } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
       }

           
   }

    /*
     * startProcessLocked()方法会去创建一个进程
     * 在点击桌面App图标,首次进入app中时会调用startProcessLocked()方法   
     * 因为首次启动App时,要去创建该App对应的进程
     * 除了app首次启动之外,app内部跳转Activity的时候都不会执行到该方法,
     */  
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}

上面的注释中已经解释的很清楚了,如果是App内部跳转Activity的话,会去执行realStartActivityLocked()方法来启动一个Activity,否则的话就会去调用ActivityManagerService的startProcessLocked()方法来创建一个该应用程序对应的进程。我们来看下这个方法。

final ProcessRecord startProcessLocked(String processName,
        ApplicationInfo info, boolean knownToBeDead, int intentFlags,
        String hostingType, ComponentName hostingName, boolean allowWhileBooting,
        boolean isolated, boolean keepIfLarge) {
    return startProcessLocked(processName, info, knownToBeDead, intentFlags, 
                          hostingType,hostingName, allowWhileBooting, isolated, 
                          0 /* isolatedUid */, keepIfLarge,null /* ABI override */, 
                          null /* entryPoint */, null /* entryPointArgs */,null /* 
                          crashHandler */);
}
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
        boolean knownToBeDead, int intentFlags, String hostingType, ComponentName 
        hostingName,boolean allowWhileBooting, boolean isolated,
        int isolatedUid, boolean keepIfLarge,String abiOverride,
        String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
        long startTime = SystemClock.elapsedRealtime();
        //该进程对应的ProcessRecord
    ProcessRecord app;
    if (!isolated) {
        //创建该进程对应的ProcessRecord对象
        app = getProcessRecordLocked(processName, info.uid, keepIfLarge);

        ......

    } else {
        ......
    }
    ......

    startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, 
                        entryPointArgs);
    return (app.pid != 0) ? app : null;
}

在上述方法中,创建了该进程对应的ProcessRecord对象,然后又调用了另一个startProcessLocked()方法

private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] 
            entryPointArgs) {
        
    ......

    try {
            
        ......

        if (entryPoint == null) entryPoint = "android.app.ActivityThread";

        ......

        ProcessStartResult startResult;
        if (hostingType.equals("webview_service")) {
            ......
        } else {
            //重点来了!!!调用Porcess.start()方法来创建一个进程
            startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags,mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi,instructionSet,
                    app.info.dataDir, invokeWith, entryPointArgs);
            }
            
            ......

        } catch (RuntimeException e) {
            ......
        }
}

在上述代码中,最终会调用Process.start()方法来创建一个进程,而ActivityThread的main()方法也是在进程常见的时候执行的(额,查了很多的资料,基本都是说是在进程创建的时候调用的ActivityThread的main()方法,但是我往下跟了跟代码,没有找到具体哪个地方调用的main()方法,我猜有可能是在native层调用的main()方法吧,另外,我们看Process.start()的第一个参数enrtyPoint,在上述截图的代码中已经很明显能看到,该参数的值是“android.app.ActivityThread”,也就是说再Process.start()的参数里,会把ActivityThread这个类的作为参数传递,所以我们也有理由相信,ActivityThread的main()方法可能也是在这个过程中执行的)

综上所述,应用程序的进程也就创建完毕了,ActivityThread的main()方法也执行了,具体在ActivityThread的main()方法中执行了哪些操作,欢迎大家看一下我的 Android Activity启动(一)Application创建的过程以及原理分析这篇博客,里面有详细的介绍

到此为止,有关App Activity跳转的流程以及原理的分析基本上已经写完了,本篇博客内容不算很多,大部分的内容在前两篇博客中已经讲过了,单独本篇内容抽离出来,也是为了更具层次和条理性。

下面我来总结一下这三篇博客的主要内容:

      当我们点击桌面的Launcher首次进入app时,会走Activity的startActivity()的过程,在启动一个新的Activity之前,会先执行“当前Activity”的onPause()方法,把当前Activity给pause掉(这里需要提一点,如果是点击桌面Launcher,首次进入app的话,这个“当前的Activity”指的就是桌面Launcher的Activity),当前Activity执行onPause()之后,如果当前应用的进程已经创建(这种情况下指的是在App内部的activity的跳转),那么就会去通过ActivityManagerService中持有的ActivityThread中的ApplicationThread这个Binder对象来立即创建一个新的Activity,并执行该Activity声明周期的方法,如果当前应用的进程没有创建(也就是首次进入app),那么这个时候会先通过Process.start()方法来创建一个进程,在创建的过程中会去调用ActivityThread的main()方法,在这个main()方法中会创建一些必备的东西比如,主线程的Looper等,并且在main()方法中会执行Application的创建过程,通过ActivityManagerService来创建一个Application,在创建完成之后,会启动一个Activity,这个Activity指的就是我们默认启动的首页Activity,也就是我们通常说的MainActivity。

欢迎大家对我针对Activity跳转流程和原理的三篇博客进行指正,感激不尽,下篇博客开始讲BroadcastReceiver的创建流程以及原理,感觉有不少相似的地方。

 

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值