Activity的启动过程解析

作者: 小鹿啊小鹿 | 来源:发表于2019-04-15 11:29 被阅读0次

问题:Activity的启动过程是怎样的?

关键词:activity,启动过程
分析角度:源码

首先启动一个Activity是通过Intent跳转,调用startActivity()来启动。
下面看startActivity的源码:

    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);
        }
    }

可以看到startActivity最终还是调用了startActivityForResult方法;

startActivityForResult的源码:

   public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
       if (mParent == null) {
           //当前Activity没有父类
           //Instrumentation 启动Activity
           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;
           }

           final View decor = mWindow != null ? mWindow.peekDecorView() : null;
           if (decor != null) {
               decor.cancelPendingInputEvents();
           }
           // TODO Consider clearing/flushing other event sources and events for child windows.
       } else {
           //当前Activity有父类,options是Bundle类型
           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);
           }
       }
       if (options != null && !isTopOfTask()) {
           mActivityTransitionState.startExitOutTransition(this, options);
       }
   }

这里只关心mParent==null 的条件
启动的时候调用了mInstrumentation.execStartActivity()方法;
看看这个源码:

Instrumentation.Java

 public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final 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();
            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) {
        }
        return null;
    }

最后调用了这个方法去startActivity:

 int result = ActivityManagerNative.getDefault()
                .startActivity

并且返回对返回结果check:

checkStartActivityResult(result, intent);

checkStartActivityResult(result, intent);这个方法中做了一些拦截异常并抛出的处理:

 public static void checkStartActivityResult(int res, Object intent) {
        if (res >= ActivityManager.START_SUCCESS) {
            return;
        }
        
        switch (res) {
            case ActivityManager.START_INTENT_NOT_RESOLVED:
            case ActivityManager.START_CLASS_NOT_FOUND:
                if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                    throw new ActivityNotFoundException(
                            "Unable to find explicit activity class "
                            + ((Intent)intent).getComponent().toShortString()
                            + "; have you declared this activity in your AndroidManifest.xml?");
                throw new ActivityNotFoundException(
                        "No Activity found to handle " + intent);

            case ActivityManager.START_PERMISSION_DENIED:
                throw new SecurityException("Not allowed to start activity "
                        + intent);
            case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
                throw new AndroidRuntimeException(
                        "FORWARD_RESULT_FLAG used while also requesting a result");
            case ActivityManager.START_NOT_ACTIVITY:
                throw new IllegalArgumentException(
                        "PendingIntent is not an activity");
            case ActivityManager.START_NOT_VOICE_COMPATIBLE:
                throw new SecurityException(
                        "Starting under voice control not allowed for: " + intent);
            default:
                throw new AndroidRuntimeException("Unknown error code "
                        + res + " when starting " + intent);
        }
    }

重要的是这一步:int result = ActivityManagerNative.getDefault().startActivity
ActivityMaagerNative.getDefault返回结果是 IActivityManager这个接口。
首先找到这个接口的实现类并找到startActivity方法:ActivityManagerNative


image.png

这个方法中最终调用了mRemote.transact来执行事务。那么mRemote是什么?


image.png

一个IBinder,所以实际上Activity的启动也是通过跨进程通信的方式实现的。

之前调用了ActivityManagerNative.getDefault(),实际上getDefault最终是一个单例实现的,最终返回IActivityManager.


image.png

相关文章

网友评论

    本文标题:Activity的启动过程解析

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