Android深入四大组件(六)Android8.0 根Activity启动过程(前篇)

相关文章
Android深入四大组件系列
Android系统启动系列
Android应用程序进程系列
Android深入解析AMS系列

前言

在几个月前我写了Android深入四大组件(一)应用程序启动过程(前篇)Android深入四大组件(一)应用程序启动过程(后篇)这两篇文章,它们都是基于Android 7.0,当我开始阅读Android 8.0源码时发现应用程序(根Activity)启动过程照Android 7.0有了一些变化,因此又写下了本篇文章,本篇文章照此前的文章不仅流程发生变化,而且增加了一些分析,算是升级版本。由于篇幅较长,Android8.0 根Activity启动过程仍旧分为前篇和后篇来进行讲解。

1.概述

Activity的启动过程分为两种,一种是根Activity的启动过程,另一种是普通Activity的启动过程,根Activity指的是应用程序启动的第一个Activity,因此根Activity的启动过程一般情况下也可以理解为应用程序的启动过程。普通Activity指的是除了应用程序启动的第一个Activity之外的其他的Activity。这里介绍的是根Activity的启动过程,它和普通Activity的启动过程是有重叠部分的,只不过根Activity的启动过程一般情况下指的就是应用程序的启动过程,更具有指导性意义。想要了解普通Activity的启动过程的的同学可以参考根Activity的启动过程去自行阅读源码。

根Activity的启动过程比较复杂,因此这里分为三个部分来讲,分别是Launcher请求AMS过程、 AMS到ApplicationThread的调用过程和ActivityThread启动Activity,本篇文章会介绍前两个部分。

2.Launcher请求AMS过程

Launcher启动后会将已安装应用程序的快捷图标显示到桌面上,这些应用程序的快捷图标就是启动根Activity的入口,当我们点击某个应用程序的快捷图标时就会通过Launcher请求AMS来启动该应用程序。时序图如下图所示。
4.1.png

当我们点击应用程序的快捷图标时,就会调用Launcher的startActivitySafely方法,如下所示。
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

   public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
        ...
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//1
        if (v != null) {
            intent.setSourceBounds(getViewBounds(v));
        }
        try {
            if (Utilities.ATLEAST_MARSHMALLOW
                    && (item instanceof ShortcutInfo)
                    && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
                     || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
                    && !((ShortcutInfo) item).isPromise()) {
                startShortcutIntentSafely(intent, optsBundle, item);
            } else if (user == null || user.equals(Process.myUserHandle())) {
                startActivity(intent, optsBundle);//2
            } else {
                LauncherAppsCompat.getInstance(this).startActivityForProfile(
                        intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
            }
            return true;
        } catch (ActivityNotFoundException|SecurityException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
        }
        return false;
    }

在注释1处设置Flag为Intent.FLAG_ACTIVITY_NEW_TASK①,这样根Activity会在新的任务栈中启动。在注释2处会调用startActivity方法,这个startActivity方法的实现在Activity中,如下所示。
frameworks/base/core/java/android/app/Activity.java

  @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            startActivityForResult(intent, -1);
        }
    }

startActivity方法中会调用startActivityForResult方法,它的第二个参数为-1,表示Launcher不需要知道Activity启动的结果,startActivityForResult方法的代码如下所示。
frameworks/base/core/java/android/app/Activity.java

 public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {//1
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
           ...
        } else {
          ...
        }
    }

注释1处的mParent是Activity类型的,表示当前Activity的父类。因为目前根Activity还没有创建出来,因此,mParent == null成立。接着调用Instrumentation的execStartActivity方法,Instrumentation主要用来监控应用程序和系统的交互,execStartActivity方法的代码如下所示。
frameworks/base/core/java/android/app/Instrumentation.java

  public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        ...
        try {
            intent.migrateExtraStreamToClipData();
     
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值