Activity启动过程浅析

Activity启动流程浅析

我们经常通过下面的代码来显示启动一个Activity,但是在这简单的操作背后,你有没有想过TargetActivity的实例是何时被创建的呢?TargetActivity又是何时进入onCreate、onStart、onResume生命周期呢?TargetActivity的DecorView又是何时被测量、布局、绘制并显示的呢?本篇文章将带你逐步探索Activity的启动流程。

Intent intent = new Intent(this, TargetActivity.class);
startActivity(intent);

    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

如上所示,位于Activity类中的startActivity方法有两个重载方法,它们最终都会调用startActivityForResult方法,我们看一下startActivityForResult方法:

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) 
    {
        startActivityForResult(intent, requestCode, null);
    }

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
    @Nullable Bundle options) {
        if (mParent == null) {
            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());
            }
            if (requestCode >= 0) {
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will 
                // keep the activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child 
            // windows.
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

通过上面的代码我们可以看到,startActivityForResult方法其实是通过调用Instrumentation的execStartActivity方法来完成Activity的启动操作的。但是在调用execStartActivity方法时会为其增加四个参数:this、mMainThread.getApplicationThread()、mToken以及this。下面简单介绍一下这四个参数:

  • this:该参数被向上转型为Context,表示了这个Activity所在的上下文环境,用于获取应用的包名;
  • mMainThread.getApplicationThread():该参数是一个ApplicationThread实例,被向上转型为IBinder,该参数在启动Activity过程中发挥着重要作用,下面会详细解释;
  • mToken:mToken也是一个IBinder类型,在Activity执行attach的时候被赋值,它用来标示正在执行启动Activity操作的对象身份,通过使用mToken,我们就可以不必把Activity自身发送给ActivityManagerService来进行身份验证;
  • this:该参数是Activity类型,表示了正在执行启动Activity操作的那个Activity,启动结果将由此Activity接收。

再看一下Instrumentation中的execStartActivity方法:

    public Instrumentation.ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final Instrumentation.ActivityMonitor am = mActivityMonitors.get(i);
                    if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManagerNative.getDefault()
                    .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;
    }

Instrumentation中通过ActivityManagerNative.getDefault().startActivity()方法完成Activity的启动。而ActivityManagerNative.getDefault()返回是一个IActicityManager类型的对象。下面看一下ActivityManagerNative.getDefault()方法:

    static public IActivityManager getDefault() {
        return gDefault.get();
    }

    private static final Singleton<IActivityManager> gDefault = new 
      Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

相信大家都知道ActivityManagerService,而ActivityManagerService继承自抽象类ActivityManagerNative,ActivityManagerNative又继承自Binder并实现了IActivityManager接口,也即ActivityManagerService是一个Binder对象。

IActivityManager接口继承自IIterface,因此IActivityManager其实是一个Binder类型的接口,而通过getDefault()方法获取的对象正是用于跟系统服务ActivityManagerService进行IPC通信。

上面可以看到gDefault是一个IActivityManager的单例,而gDefault.get()返回的正是asInterface(IBinder),也即是一个ActivityManagerProxy实例,用于在客户程序中发起IPC过程。因此,ActivityManagerNative.getDefault() .startActivity()的调用其实是一个IPC过程,服务端正是ActivityManagerService,startActivity方法如下:。

    public int startActivity(IApplicationThread caller, String callingPackage, Intent 
                             intent, String resolvedType, IBinder resultTo, String 
                             resultWho, int requestCode, int startFlags, ProfilerInfo 
                             profilerInfo, Bundle options) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }

看到这里,相信大家都很清楚了,Activity的启动过程的前半部分总结如下:

  1. 调用Activity类的startActivity或者starActivityForResult方法来启动Activity,最终调用会传递到Activity类中的startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options)方法;
  2. startActivityForResult方法中会调用mInstrumentation.execStartActivity()方法,mInstrumentation是一个Instrumentation对象,在Activity执行attach时被赋值;
  3. Instrumentation中通过ActivityManagerNative.getDefault()来获取一个远程ActivityManagerService通过asInterface()转换为IActivityManager后的对象;
  4. 通过调用IActivityManager对象的startActivity方法,进行IPC调用,向ActivityManagerService请求启动Activity;

读者熟悉AIDL的话应该可以知道,在上面的startActivity方法中调用了mRemote.transact之后,就启动了IPC过程,然后onTransact中相应的代码会在服务端Binder线程池中执行,我们看一下onTransact方法:

    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
        case START_ACTIVITY_TRANSACTION:
        {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            String callingPackage = data.readString();
            Intent intent = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            IBinder resultTo = data.readStrongBinder();
            String resultWho = data.readString();
            int requestCode = data.readInt();
            int startFlags = data.readInt();
            ProfilerInfo profilerInfo = data.readInt() != 0
                    ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
            Bundle options = data.readInt() != 0
                    ? Bundle.CREATOR.createFromParcel(data) : null;
            int result = startActivity(app, callingPackage, intent, resolvedType,
                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
            reply.writeNoException();
            reply.writeInt(result);
            return true;
        }
        //Other case。。
        //此处省略3k行。。
    }

该方法运行在system_process进程环境中,因此如果我们要debug跟踪此方法的话需要attach debugger到该进程。可以看到,在该方法中,会从data中读取相应的请求数据,然后调用ActivityManagerService中的startActivity方法。

看一下ActivityManagerService中的startActivity方法:

    final int startActivity(Intent intent, ActivityStackSupervisor.ActivityContainer 
                            container) {
        enforceNotIsolatedCaller("ActivityContainer.startActivity");
        final int userId = mUserController.handleIncomingUser(Binder.getCallingPid(),
                Binder.getCallingUid(), mStackSupervisor.mCurrentUser, false,
                ActivityManagerService.ALLOW_FULL_ONLY, "ActivityContainer", null);

        // TODO: Switch to user app stacks here.
        String mimeType = intent.getType();
        final Uri data = intent.getData();
        if (mimeType == null && data != null && "content".equals(data.getScheme())) {
            mimeType = getProviderMimeType(data, userId);
        }
        container.checkEmbeddedAllowedInner(userId, intent, mimeType);

        intent.addFlags(FORCE_NEW_TASK_FLAGS);
        return mActivityStarter.startActivityMayWait(null, -1, null, intent, mimeType, 
                                                     null, null, null, null, 0, 0, null, 
                                                     null, null, null, false, userId, 
                                                     container, null);
    }

此处先暂时省略在ActivityStarter、ActivityStack、ActivityStackSupervisor中执行的一系列操作(后面的文章会详细分析ActivityManagerService所做的工作),直接看在ActivityStackSupervisor中的realStartActivityLocked方法,该方法中有下面一处调用:

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), 
                    r.info, new Configuration(mService.mConfiguration),
                    new Configuration(task.mOverrideConfig), r.compat, 
                    r.launchedFromPackage, task.voiceInteractor, app.repProcState, 
                    r.icicle, r.persistentState, results, newIntents, !andResume, 
                    mService.isNextTransitionForward(), profilerInfo);

其中app.thread是一个IApplicationThread类型,还记得我们在一开始的时候说过ApplicationThread在Activity启动过程中发挥着重要作用吗?在开始时通过mMainThread.getApplicationThread获得的ApplicationThread对象被向上转型为IBinder后通过IPC过程传递给ActivityManagerService。而app.thread就是该IBinder对象所对应的服务端本地对象。

再来看一下ApplicationThread,ApplicationThread是ActivityThread的内部类,它继承自抽象类ApplicationThreadNative,而ApplicationThreadNative则继承了Binder类并实现了IApplicationThread接口,在IApplicationThread接口中声明了大量的有关Activity以及Service生命周期的方法。那么,ApplicationThread也就是一个Binder,通过app.thread.scheduleLaunchActivity的调用也同样是一个IPC调用,而此时的服务方运行在进行启动Activity操作的进程中,通常也就是我们的应用程序所在的进程。

现在,Activity的启动过程已经重新切换到了起初的进程中,剩下的操作由ApplicationThread中的scheduleLaunchActivity方法完成。看一下scheduleLaunchActivity方法:

        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor 
                voiceInteractor, int procState, Bundle state, 
                PersistableBundle persistentState, List<ResultInfo> pendingResults, 
                List<ReferrerIntent> pendingNewIntents, boolean notResumed, 
                boolean isForward, ProfilerInfo profilerInfo) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;

            //……

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

可以看到scheduleLaunchActivity方法中只是简单的提取参数封装到一个ActivityClientRecord对象中,然后调用了sendMessage方法:

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();

        Log.e("ActivityThreaddd", "sendMessage");

        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

在sendMessage方法中构造了一个Message,然后将其发送给mH。mH是ActivityThread中内部类H的实例,而H类继承自Handler,也即mH其实是一个Handler,剩下的处理流程将交由H的handleMessage来处理。

这里有一个问题,就是为什么要通过Handler来通信,而不是直接调用相应的处理逻辑?如果了解Binder的话,这个问题就很容易回答了,因为scheduleLaunchActivity方法的调用是一个IPC过程,也即scheduleLaunchActivity方法是在Binder线程池中执行的,因此需要使用Handler将任务切换到主线程。

现在看一下mH这个Handler的handleMessage方法:

    public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                r.packageInfo = getPackageInfoNoCheck(
                                r.activityInfo.applicationInfo, r.compatInfo);
                handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            } break;
            //other cases...

在handleMessage方法中通过handleLaunchActivity方法来完成Activity的启动:

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        //……

        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && 
                                 !r.startsNotResumed, r.lastProcessedSeq, reason);
            //……
    }

在handleLaunchActivity中会通过performLaunchActivity方法完成Activity的onCreate、onStart过程,然后并会通过handleResumeActivity方法完成onResume过程,下面看一下performLaunchActivity方法:

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        //……

        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
            //……
            if (activity != null) {
                //……
                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);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                //……
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                //……
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }

                //……

        return activity;
    }

在performLaunchActivity方法中,首先创建Activity的实例,该过程在Instrumentation中由ClassLoader完成,然后通过makeApplication方法来创建Application实例,如果Application已经创建,那么在makeApplication方法中会直接返回该实例。之后,会执行Activity的attach方法, 为activity初始化一些重要的数据域。然后,通过callActivityOnCreate方法来调用Activity的performCreate方法,performCreate方法中会调用onCreate方法,最后会调用activity.performStart()方法,完成activity的onStart过程。

而Activity中的View的添加过程则是通过setContentView方法完成的,setContentView方法会调用PhoneWindow的setContentView方法,而PhoneWindow的setContentView方法中会通过installDecor方法来创建DecorView,然后通过LayoutInflater来将布局文件添加到DecorView的ContentParent中。

而Activity变为可见状态也是在handleResumeActivity方法里执行的,在通过调用performResumeActivity方法完成Activity的onResume之后,会调用通过WindowManager的addView来添加Window,在添加Window时会执行View的measure、layout以及draw过程,然后通过Activity的makeVisible方法使DecorView变为可见状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值