美文网首页
Activity启动流程分析记录(Api26)

Activity启动流程分析记录(Api26)

作者: r09er | 来源:发表于2018-01-24 23:04 被阅读28次

直观流程图

图1-1 Activity启动流程

具体流程分析

  1. Activity调用startActivity,虽然startActivity有很多重载函数,但是最终也会调用Activity中的startActivityForResult方法,在startActivityForResult中有一个mParent的null判断,mParent代表的是ActivityGroup,ActivityGroup用于在一个Activity中放入多个子Activity,已经被废弃,使用Fragmemt和FragmentManager替代,所以主要看mParent==null
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            //调用Instrumentation的execStartActivity方法
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            //返回结果不为空,证明返回的intent中含有参数,将参数作为结果返回
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
          
            if (requestCode >= 0) {
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
        } else {
           ....忽略
        }
    }
  1. 在Instrumentation.execStartActivity方法代码,具体关注ActivityManager.getService().startActivity方法
 public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);

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

上面这段代码中,可以发现启动Activity真正的实现由ActivityManager.getService()的startActivity方法完成,ActivityManager.getService()方法其实是一个IActivityManager类型的Binder对象,这个Binder对象使用一个单例模式进行封装,保证全局只有一个IActivityManager对象.
在执行完 ActivityManager.getService().startActivity方法后,还有一句checkStartActivityResult(result , intent);这句代码就是用于检查启动的Activity的结果,当无法正常启动Activity的时候,就会抛出异常,其中最常见的一个异常信息就是

Unable to find explicit activity class ** have you declared this activity in your AndroidManifest.xml?

  1. 通过上面的流程分析,现在发现具体的Activity启动主要就是在AMS中的startActivity方法.AMS中的startActivity又调用了startActivityAsUser方法,这里又将Activity的启动转移到了ActivityStarter的startActivityMayWait方法中,
  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(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        ...
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null,
                "startActivityAsUser");
    }
  1. 饶了一大圈其实就是在ActivityStarter内部,ActivityStack,ActivityStackSupervisor之间不断调用,最终落在ActivityStackSupervisor的realStartActivityLocked方法中,其中注意方法中以下代码
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,                    // override configs.
                    mergedConfiguration.getGlobalConfiguration(),
                    mergedConfiguration.getOverrideConfiguration(), r.compat,
                    r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                    r.persistentState, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profilerInfo);

scheduleLaunchActivity这个方法是在realStartActivityLocked中被调用的,app.thread对象是IApplicationThread,这个IApplicationThread是一个IBinder对象,这个接口的实现类在ActivityThread中,一个私有的内部类,ApplicationThread ,该类继承自IApplicationThread.Stub,实现了IApplicationThread所有的抽象方法.

scheduleLaunchActivity就是启动Activity的方法,通过发送一个启动activity的消息交给handler处理,handler接收到消息后调用handleLaunchActivity方法,然后调用了handleResumeActivity方法调用被启动的Activity的onResume生命周期方法.

 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) {

          ...
            sendMessage(H.LAUNCH_ACTIVITY, r);
}

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

handleLaunchActivity中调用了performLaunchActivity和handleResumeActivity方法

  1. 在performLaunchActivity中,通过调用了Instrumentation的newActivity方法,通过反射创建了Activity对象,调用LoadedApk中的makeApplication创建了Application对象,其内部实现也是通过反射.
 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

忽略部分初始化代码...
          //创建Context的实现类
          ContextImpl appContext = createBaseContextForActivity(r);

            //创建Activity对象
            java.lang.ClassLoader cl = appContext.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);
            }

...
            //创建Application对象
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
...

//Activity与Context建立联系,同时完成Activity与Window的关联.
 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的启动流程大体如此,大部分逻辑都是参考<<Android开发艺术探索>>,但是由于书中的源码版本是Android5.0,而我在学习的时候使用的源码是Android8.0,所以可能会有部分代码有出入,但是整体结构和逻辑都是一样的,并不影响对Activity启动的掌握

相关文章

网友评论

      本文标题:Activity启动流程分析记录(Api26)

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