startActivity()流程分析

2020-05-28  本文已影响0人  Hsicen
startActivity() 流程分析 (SDK源码为28)

当我们从手机桌面点击应用图标时,这时候就会打开我们的应用程序,在这个过程中发生了什么事情,整个流程是怎么样的?我们知道在Android中一个App就相当于一个进程,点击应用icon时就相当于从一个进程跳转到了另一进程。在这里就涉及到了跨进程通讯,Android系统中是通过Binder来实现进程通讯的,是由ActivityThread的内部类ApplicationThread来完成的,这里主要涉及到了三个阶段:

针对Android系统来说,手机桌面也是页面,应用icon是这个页面展示的数据;手机桌面是通过Launcher类来实现的,Launcher继承自Activity,手机厂商自定义桌面都是通过实现Launcher来实现的,我们首先来看它的onClick方法,这里面记录了我们点击应用icon后的操作逻辑:

public void onClick(View v) {
    Object tag = v.getTag();
    
    if (tag instanceof ShortcutInfo) { //点击应用icon
        final Intent intent = ((ShortcutInfo) tag).intent;
        boolean success = startActivitySafely(v, intent, tag);
    } else if (tag instanceof FolderInfo) {//点击文件夹,主要是应用分类
        if (v instanceof FolderIcon) {
            FolderIcon fi = (FolderIcon) v;
            handleFolderClick(fi);
        }
    } else if (v == mAllAppsButton) {//点击显示所有应用icon
        if (isAllAppsVisible()) {
            showWorkspace(true);
        } else {
            onClickAllAppsButton(v);
        }
    }
}

这里我们主要关注点击应用icon的逻辑处理,因为后面两种点击逻辑处理最终都会调用点击应用icon的梳理逻辑,接下来我们进入startActivitySafely()方法

boolean startActivitySafely(View v, Intent intent, Object tag) {
    boolean success = false;
    try {
        success = startActivity(v, intent, tag);
    } catch (ActivityNotFoundException e) {
        Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
        Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
    }
    return success;
}

这个方法主要对startActivity()进行了一层包装,进行异常处理,然后进入startActivity()

boolean startActivity(View v, Intent intent, Object tag) {
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //在新的任务栈中启动
                    
    try {
        UserHandle user = (UserHandle) intent.getParcelableExtra(ApplicationInfo.EXTRA_PROFILE);
        LauncherApps launcherApps = (LauncherApps)
                this.getSystemService(Context.LAUNCHER_APPS_SERVICE);
        
        if (user == null || user.equals(android.os.Process.myUserHandle())) {
            startActivity(intent, opts.toBundle()); //调用Activity的startActivity()
        } else {
            launcherApps.startMainActivity(intent.getComponent(), user,
                                           intent.getSourceBounds(),
                                           opts.toBundle());
        }
        
        return true;
    } catch (SecurityException e) {
        Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
    }
    return false;
}

这里主要分了两步走,我们首先看Activity#startActivity()

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

Activity#startActivity()重写了父类ContextWrapper的startActivity(),然后调用了startActivityForResult(),传入-1的作用是不需要返回结果

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,@Nullable Bundle options) {
    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());
    }
}

以上代码我只摘抄了主要部分,方便理解,在startActivityForResult中调用了Instrumentation#execStartActivity(),这个Instrumentation是用来监控应用程序和系统交互的,mMainThread.getApplicationThread()是一个IBinder接口,用于实现进程间通讯的。

public ActivityResult execStartActivity(Context who, IBinder contextThread ...) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    
    try {
        int result = ActivityTaskManager.getService()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
}

可以发现,在这里获取了ActivityAIApplicationThread,然后通过ActivityTaskManager获取了ActivityManagerService,并调用了其startActivity,这一步实现了ActivityAActivityManagerService的过渡,启动ActivityB的任务就交由AMS来实现。

接下来我们来看Server端启动Activity的流程,首先我们进入AMS#startActivity()

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());
}
public final int startActivityAsUser() {
    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();
}

在这里我们获取了一个ActivityStarter,然后采用Builder模式设置了一些参数,最后调用了execute;看名字这个ActivityStarter是专门用来启动Activity的,接下来我们进入这个类,查看execute做了什么处理

int execute() {
    if (mRequest.mayWait) {
        return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
                mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
                mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                mRequest.inTask, mRequest.reason,
                mRequest.allowPendingRemoteAnimationRegistryLookup);
    } else {
        return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
                mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
                mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
                mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
                mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
                mRequest.outActivity, mRequest.inTask, mRequest.reason,
                mRequest.allowPendingRemoteAnimationRegistryLookup);
    }
}

startActivityMayWaitstartActivity中主要做了解析Intent,创建ActivityRecord,创建TaskRecord等工作;最终这两个方法都会调用ActivityStarter#startActivityUnchecked()

private int startActivityUnchecked() {
    //启动Flag计算
    computeLaunchingTaskFlags();
    
    //处理Task和Activity的进站操作
    mTargetStack.startActivityLocked();
    
    //处理栈顶Activity
    mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,mOptions);
}
boolean resumeFocusedStackTopActivityLocked() {

    if (targetStack != null && isFocusedStack(targetStack)) {
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
    
    final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
    if (r == null || !r.isState(RESUMED)) {
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    } else if (r.isState(RESUMED)) {
        mFocusedStack.executeAppTransition(targetOptions);
    }
    
    return false;
}

上面几个判断最终都会调用ActivityStack#resumeTopActivityUncheckedLocked

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    boolean result = false;
    result = resumeTopActivityInnerLocked(prev, options);
    
    return result;
}

ActivityStack#resumeTopActivityInnerLocked()中会经过一些列的判断,最后调用ActivityStackSupervisor#startSpecificActivityLocked()方法

void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);
    
    if (app != null && app.thread != null) {
        realStartActivityLocked(r, app, andResume, checkConfig);
        return;
    }
    
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}

在这里会判断ActivityB所在的应用进程是否存在,如果进程不存在,会先去创建进程,最后会调用realStartActivityLocked,我们再进入ActivityStackSupervisor#realStartActivityLocked(),查看做了什么逻辑

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
    
    // Create activity launch transaction. 创建transaction
    final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,r.appToken);
    
    //添加Callback回调接口,稍后会执行
    clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
        System.identityHashCode(r), 
        r.info,
        mergedConfiguration.getGlobalConfiguration(),
        mergedConfiguration.getOverrideConfiguration(), 
        r.compat,
        r.launchedFromPackage, 
        task.voiceInteractor, 
        app.repProcState, 
        r.icicle,
        r.persistentState, 
        results, 
        newIntents, 
        mService.isNextTransitionForward(),
        profilerInfo));
    
    // Schedule transaction.  执行transaction
    mService.getLifecycleManager().scheduleTransaction(clientTransaction);
}

可以看到最后获取了ClientLifecycleManager,然后执行了scheduleTransaction(),然后进入这个方法

void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    final IApplicationThread client = transaction.getClient();
    transaction.schedule();
}

在这里Transaction的client,这个client是IApplicationThread类型,这个类是用于进程间通讯的,有可能这里会使用client来和AMS通信,后面会不会使用它,我们向下分析就知道了,最后这个方法执行了transaction.schedule()

public void schedule() throws RemoteException {
    mClient.scheduleTransaction(this);
}

果然这里使用利用client实现了ActivityB所在的进程和AMS所在进程进行通讯,调用了ActivityB所在进程的IApplicationThread的scheduleTransaction(),这里Activity启动任务实现了从AMS到ActivityB所在进程的交接

这下startActivity任务来到第三阶段,AMS通过Binder通信,把启动ActivityB的任务交由ActivityB所在进程处理,ActivityB所在进程的ApplicationThreadscheduleTransaction()方法被调用

@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    ActivityThread.this.scheduleTransaction(transaction);
}

在ActivityThread方法中会找不到scheduleTransaction,因为调用的是其父类ClientTransactionHandler#scheduleTransaction()

void scheduleTransaction(ClientTransaction transaction) {
    transaction.preExecute(this);
    sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}

在这个方法中,先调用了preExecute()做了一些预处理工作,然后向ActivityThread所在线程的Handler发送了一条消息EXECUTE_TRANSACTION;这个时候直接查看这个名为H的Handler的handleMessage()做了什么处理逻辑

public void handleMessage(Message msg) {
    case EXECUTE_TRANSACTION:
        final ClientTransaction transaction = (ClientTransaction) msg.obj;
        mTransactionExecutor.execute(transaction);
        if (isSystem()) {
            transaction.recycle();
        }
        break;
}

Handler在收到这条消息后,调用TransactionExecutor#execute()

public void execute(ClientTransaction transaction) {
    executeCallbacks(transaction);
    executeLifecycleState(transaction);
}
public void executeCallbacks(ClientTransaction transaction) {
    final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
    final int size = callbacks.size();
    
    for (int i = 0; i < size; ++i) {
        final ClientTransactionItem item = callbacks.get(i);
        item.execute(mTransactionHandler, token, mPendingActions);
        item.postExecute(mTransactionHandler, token, mPendingActions);
    }
}

这里会获取到transaction的所有Callback对象,然后依次执行它们的execute方法,那么这些Callback是什么时候添加的呢?还记得我们创建Transaction的时候么,创建Transaction对象时,我们往里面添加了Callback对象LaunchActivityItem,这里我们只需要查看LaunchActivityItem的execute做了什么处理就行 (LaunchActivityItem是继承自ClientTransactionItem)

public void execute(ClientTransactionHandler client ...) {
    ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
            mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
            mPendingResults, mPendingNewIntents, mIsForward,
            mProfilerInfo, client);
    client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
}

这里调用了ClientTransactionHandler#handleLaunchActivity,其实就是调用的ActivityThread的handleLaunchActivity(),因为ActivityThread是ClientTransactionHandler的实现类

public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
    WindowManagerGlobal.initialize();
    final Activity a = performLaunchActivity(r, customIntent);
}

首先创建WindowManagerService,进行Window初始化相关操作;然后再调用performLaunchActivity()处理Activity的创建逻辑

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    //第一步:创建Activity的Context
    ContextImpl appContext = createBaseContextForActivity(r);

    //第二步:创建Activity实例
    Activity activity = null;
    java.lang.ClassLoader cl = appContext.getClassLoader();
    activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
    
    //第三步:获取当前进程的application实例
    Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    //LoadedApk的makeApplication
    app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
    
    //第三步:执行Activity的attach方法
    //创建PhoneWindow,设置mWindow#setCallback(),设置mWindowManager,设置mApplication
    activity.attach(appContext, this, getInstrumentation(), r.token,
        r.ident, app, r.intent, r.activityInfo, title, r.parent,
        r.embeddedID, r.lastNonConfigurationInstances, config,
        r.referrer, r.voiceInteractor, window, r.configCallback);
    
    //第四步:调用Activity的onCreate()
    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
}

到此从ActivityA到ActivityB的启动流程已经完成,ActivityB成功启动,并调用了其onCreate(),如还需要分析后续流程,就应该是View的绘制流程了

到最后,我们对这个流程做一个总结:

上一篇下一篇

猜你喜欢

热点阅读