美文网首页
四大组件的工作过程

四大组件的工作过程

作者: 沐小晨曦 | 来源:发表于2018-11-25 17:39 被阅读57次

根 Activity 启动过程

根 Activity 的启动过程一般也可以理解为应用程序的启动过程。

根 Activity 的启动过程比较复杂,可以分为三个部分:

  1. Launcher 请求 AMS 过程
  2. AMS 到 ApplicationThread 的调用过程
  3. ActivityThread 启动 Activity
Launcher 请求 AMS 过程

整个流程图为:

image

Launcher 其实也是一个 Activity,( Launcher extend BaseActivity )。

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

当我们点击应用程序的快捷图标时,就会调用 Launcher 的 startActivitySafely 方法:

    public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
        //...
        // Prepare intent
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //新的任务栈
        if (v != null) {
            intent.setSourceBounds(getViewBounds(v));
        }
        try {
            //...
            startActivity(intent, optsBundle);  //启动根 Activity
            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;
    }

上面提到 Launcher 其实也是一个 Activity,而这个 startActivity 在 Activity 中的实现是:

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

然后就传到了 startActivityForResult 方法,它的第二个参数为 -1,表示 Launcher 不需要知道 Activity 启动的结果。

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

mParent 是 Activity 类型的,表示当前 Activity 的父类,因为此时启动的是根 Activity,所以 mParent == null 成立,接着就到 Instrumentation 的 execStartActivity 方法,Instrumentation 主要用来监控应用程序和系统的交互。Instrumentation#execStartActivity 方法如下:

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        //...
        try {
            //...
            int result = ActivityManager.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;
    }

首先通过 ActivityManager#getService 方法来获取 AMS 代理对象,接着调用它的 startActivity 方法。

    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    //获取 IBinder 类型的 AMS 引用
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    //再转换成 IActivityManager 类型,采用的是 ALDL
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
AMS 到 ApplicationThread 的调用过程

第一步已经把 startActivity 的请求转给了 AMS 的 startActivity,该方法源码为:

    @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 方法,该方法比 startActivity 多最后一个参数 UserHandle.getCallingUserId ,这个方法会获得调用者的 UserId,AMS 根据这个 UserId 来确定调用者的权限。

AMS#startActivityAsUser:

    public final 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) {
        //判断调用者进程是否被隔离
        enforceNotIsolatedCaller("startActivity");
        //检查调用者权限
        userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        // TODO: Switch to user app stacks here.
        return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();

    }

看名字能猜到它是启动 Activity 的控制类,ActivityStartController#obtainStarter:

    ActivityStarter obtainStarter(Intent intent, String reason) {
        return mFactory.obtain().setIntent(intent).setReason(reason);
    }

相关文章

网友评论

      本文标题:四大组件的工作过程

      本文链接:https://www.haomeiwen.com/subject/pyapqqtx.html