四大組件的工作過程

根 Activity 啟動過程

根 Activity 的啟動過程一般也可以理解為應(yīng)用程序的啟動過程。

根 Activity 的啟動過程比較復(fù)雜,可以分為三個部分:

  1. Launcher 請求 AMS 過程
  2. AMS 到 ApplicationThread 的調(diào)用過程
  3. ActivityThread 啟動 Activity
Launcher 請求 AMS 過程

整個流程圖為:

image

Launcher 其實也是一個 Activity,( Launcher extend BaseActivity )。

Launcher 啟動后會將已安裝的應(yīng)用程序的快捷圖標顯示在桌面上,這些圖標就是啟動根 Activity 的入口,當我們點擊圖標時,就會通過 Launcher 請求 AMS 來啟動應(yīng)用程序。

當我們點擊應(yīng)用程序的快捷圖標時,就會調(diào)用 Launcher 的 startActivitySafely 方法:

    public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
        //...
        // Prepare intent
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //新的任務(wù)棧
        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 中的實現(xiàn)是:

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

然后就傳到了 startActivityForResult 方法,它的第二個參數(shù)為 -1,表示 Launcher 不需要知道 Activity 啟動的結(jié)果。

    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 主要用來監(jiān)控應(yīng)用程序和系統(tǒng)的交互。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 代理對象,接著調(diào)用它的 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);
                    //再轉(zhuǎn)換成 IActivityManager 類型,采用的是 ALDL
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
AMS 到 ApplicationThread 的調(diào)用過程

第一步已經(jīng)把 startActivity 的請求轉(zhuǎn)給了 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());
    }

直接返回調(diào)用了 startActivityAsUser 方法,該方法比 startActivity 多最后一個參數(shù) UserHandle.getCallingUserId ,這個方法會獲得調(diào)用者的 UserId,AMS 根據(jù)這個 UserId 來確定調(diào)用者的權(quán)限。

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) {
        //判斷調(diào)用者進程是否被隔離
        enforceNotIsolatedCaller("startActivity");
        //檢查調(diào)用者權(quán)限
        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);
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容