Activity启动过程详解

作者: zhuzhiqiang00 | 来源:发表于2018-03-28 11:13 被阅读34次

    Activity组件的主要作用是展示一个界面并和用户交互,它扮演的是一种前台界面的角色,在显示调用的情形下,只需要通过如下代码即可完成。

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

    通过上面代码即可启动一个具体的Activity,然后这个Activity就会被系统启动并展示在用户的眼前,但是系统内部是如何启动一个Activity的呢?比如新Activity的对象是何时创建的,onCreate方法又是在何时回调的等等,本文将针对这些问题对Activity的整体流程进行讲解。

    我们从Activity的startActivity方法开始分析,startActivity的方法有好几种重载方式,它们最终会调用startActivityForResult,它的实现如下所示。

    public void startActivityForResult(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());
                }
                ...ignore some code...    
            } else {
                if (options != null) {
                     //当现在的Activity有父Activity的时候会调用,但是在startActivityFromChild()内部实际还是调用的mInstrumentation.execStartActivity()
                    mParent.startActivityFromChild(this, intent, requestCode, options);
                } else {
                    mParent.startActivityFromChild(this, intent, requestCode);
                }
            }
             ...ignore some code...    
        }
    

    上面代码我们只关注mParent=null这部分逻辑就行,需注意mMainThread.getApplicationThread()这个参数,它的类型是ApplicationThread,ApplicationThread是ActivityThread的一个内部类,ApplicationThread和ActivityThread在Activity的启动过程中发挥着很重要的作用。接着看Instrumentation的execStartActivity方法,代码如下。

    public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
            IApplicationThread whoThread = (IApplicationThread) contextThread;
                ...ignore some code...
          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;
        }
    

    从上面代码可以看出,启动Activity真正的实现由ActivityManagerNative.getDefault()的startActivity方法来完成,
    这里的ActivityManagerNative.getDefault返回的就是ActivityManagerService的远程接口,即ActivityManagerProxy。

    public abstract class ActivityManagerNative extends Binder implements IActivityManager
    {
    
    //从类声明上,我们可以看到ActivityManagerNative是Binder的一个子类,而且实现了IActivityManager接口
     static public IActivityManager getDefault() {
            return gDefault.get();
        }
    
     //通过单例模式获取一个IActivityManager对象,这个对象通过asInterface(b)获得
     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;
            }
        };
    }
    
    
    //最终返回的还是一个ActivityManagerProxy对象
    static public IActivityManager asInterface(IBinder obj) {
            if (obj == null) {
                return null;
            }
            IActivityManager in =
                (IActivityManager)obj.queryLocalInterface(descriptor);
            if (in != null) {
                return in;
            }
        
         //这里面的Binder类型的obj参数会作为ActivityManagerProxy的成员变量保存为mRemote成员变量,负责进行IPC通信
            return new ActivityManagerProxy(obj);
        }
    
    
    }
    

    再看ActivityManagerProxy.startActivity(),在这里面做的事情就是IPC通信,利用Binder对象,调用transact(),把所有需要的参数封装成Parcel对象,向AMS发送数据进行通信。

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

    ActivityManagerProxy只是通过这种方式对要传输给服务器的数据进行打包,真正实现的是ActivityManagerService。

    但是这个地方并不是直接由客户端传递给服务器,而是通过Binder驱动进行中转。Binder驱动原理暂时忽略,我们把他当做一个中转站就OK,客户端调用ActivityManagerProxy接口里面的方法,把数据传送给Binder驱动,然后Binder驱动就会把这些东西转发给服务器的ActivityManagerServices,由ActivityManagerServices去真正的实施具体的操作。

    客户端:ActivityManagerProxy =====>Binder驱动=====> ActivityManagerService:服务端

    从上面的分析看,,ActivityManagerNative.getDefault()实际上是AMS,因此Activity的启动过程转移到了AMS中,接着我们分析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 options) {
            return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, options,
                UserHandle.getCallingUserId());
        }
    
    @Override
        public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
                Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
                
                ...ignore some code...
                
            return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                    resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                    profilerInfo, null, null, options, userId, null, null);
        }
    
    

    可以看出,Activity的启动过程又转移到了ActivityStackSupervisor的startActivityMayWait方法中了,在startActivityMayWait中又调用了startActivityLocked方法,然后startActivityLocked方法又调用了startActivityUncheckedLocked(),此时要启动的Activity已经通过检验,被认为是一个正当的启动请求。终于,在这里调用到了ActivityStack的startActivityLocked(ActivityRecord r, boolean newTask,boolean doResume, boolean keepCurTransition, Bundle options)。
    ActivityRecord代表的就是要开启的Activity对象,里面分装了很多信息,比如所在的ActivityTask等,如果这是首次打开应用,那么这个Activity会被放到ActivityTask的栈顶。

    ActivityStack.startActivityLocked()方法如下:
    final void startActivityLocked(ActivityRecord r, boolean newTask,
                boolean doResume, boolean keepCurTransition, Bundle options) {
            
            //ActivityRecord中存储的TaskRecord信息
            TaskRecord rTask = r.task;
          
             ...ignore some code...
          
            //如果不是在新的ActivityTask(也就是TaskRecord)中的话,就找出要运行在的TaskRecord对象
         TaskRecord task = null;
            if (!newTask) {
                boolean startIt = true;
                for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
                    task = mTaskHistory.get(taskNdx);
                    if (task.getTopActivity() == null) {
                        // task中的所有Activity都结束了
                        continue;
                    }
                    if (task == r.task) {
                        // 找到了
                        if (!startIt) {
                            task.addActivityToTop(r);
                            r.putInHistory();
                            mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
                                    r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
                                    (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
                                    r.userId, r.info.configChanges, task.voiceSession != null,
                                    r.mLaunchTaskBehind);
                            if (VALIDATE_TOKENS) {
                                validateAppTokensLocked();
                            }
                            ActivityOptions.abort(options);
                            return;
                        }
                        break;
                    } else if (task.numFullscreen > 0) {
                        startIt = false;
                    }
                }
            }
    
          ...ignore some code...
    
            // Place a new activity at top of stack, so it is next to interact
            // with the user.
            task = r.task;
            task.addActivityToTop(r);
            task.setFrontOfTask();
    
            ...ignore some code...
    
             if (doResume) {
                mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
            }
        }
    

    从ActivityStackSupervisor到ActivityStack,又调回ActivityStackSupervisor, 看下StackSupervisor.resumeTopActivitiesLocked(this, r, options)

    boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
                Bundle targetOptions) {
            if (targetStack == null) {
                targetStack = getFocusedStack();
            }
            // Do targetStack first.
            boolean result = false;
            if (isFrontStack(targetStack)) {
                result = targetStack.resumeTopActivityLocked(target, targetOptions);
            }
            
              ...ignore some code...
            
            return result;
        }
    

    又调回ActivityStack的resumeTopActivityLocked()方法

    final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
            if (inResumeTopActivity) {
                // Don't even start recursing.
                return false;
            }
    
            boolean result = false;
            try {
                // Protect against recursion.
                inResumeTopActivity = true;
                result = resumeTopActivityInnerLocked(prev, options);
            } finally {
                inResumeTopActivity = false;
            }
            return result;
        }
    

    然后调用ActivityStack的resumeTopActivityInnerLocked(prev, options)方法,resumeTopActivityInnerLocked方法又调用了ActivityStackSupervisor的startSpecificActivityLocked方法,源码如下:

    startSpecificActivityLocked(ActivityRecord r,
        boolean andResume, boolean checkConfig) {
            // Is this activity's application already running?
            ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                    r.info.applicationInfo.uid, true);
    
           r.task.stack.setLaunchTime(r);
    
            if (app != null && app.thread != null) {
                try {
                    if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                            || !"android".equals(r.info.packageName)) {
                        // Don't add this if it is a platform component that is marked
                        // to run in multiple processes, because this is actually
                        // part of the framework so doesn't make sense to track as a
                        // separate apk in the process.
                        app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                               mService.mProcessStats);
                    }
                    realStartActivityLocked(r, app, andResume, checkConfig);
                    return;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting activity "
                            + r.intent.getComponent().flattenToShortString(), e);
                }
    
                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
            mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                    "activity", r.intent.getComponent(), false, false, true);
        }
    

    从上面代码可以看出startSpecificActivityLocked 方法调用了realStartActivityLocked,为了更清晰地说明Activity的启动过程在ActivityStackSupervisor和ActivityStack之间传递顺序,下面给出一张图。

    在ActivityStackSupervisor的realStartActivityLocked方法中有如下一段代码:
      app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                      System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                       r.compat, r.launchedFromPackage, r.task.voiceInteractor, app.repProcState,
                      r.icicle, r.persistentState, results, newIntents, !andResume,
                      mService.isNextTransitionForward(), profilerInfo);
    
    ActivityStackSupervisor和ActivityStack之间传递顺序.png

    app.thread. scheduleLaunchActivity,实际是调用ApplicationThreadProxy.scheduleLaunchActivity()方法,ApplicationThreadProxy是ApplicationThreadNative的内部类

    客户端:ApplicationThread <=====Binder驱动<===== ApplicationThreadProxy:服务端

    这里和上面的逻辑一样。ApplicationThreadProxy把数据封装好,利用Binder对象,调用transact(),把所有需要的参数封装成Parcel对象,向发送ApplicationThread数据,绕了一大圈,Activity的启动过程最终回到了ApplicationThread,ApplicationThread通过scheduleLaunchActivity启动Activity,代码如下所示

     public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                    ActivityInfo info, Configuration curConfig, 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;
                 r.intent = intent;
                r.referrer = referrer;
                r.voiceInteractor = voiceInteractor;
                 r.activityInfo = info;
                 r.compatInfo = compatInfo;
                 r.state = state;
                r.persistentState = persistentState;
    
                r.pendingResults = pendingResults;
                r.pendingIntents = pendingNewIntents;
     
                 r.startsNotResumed = notResumed;
                r.isForward = isForward;
    
                r.profilerInfo = profilerInfo;
    
                 updatePendingConfiguration(curConfig);
    
                 sendMessage(H.LAUNCH_ACTIVITY, r);
            }
    

    在ApplicationThread中,scheduleLaunchActivity实现很简单,就是发送一个启动的消息(H.LAUNCH_ACTIVITY)交给Handler处理,这个Handler就叫H,接着看一下Handler对消息的处理

    private class H extends Handler {
            public static final int LAUNCH_ACTIVITY         = 100;
            public static final int PAUSE_ACTIVITY          = 101;
    
                //ignore some code
    
            public vhandleMessage(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);
                      Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                   } break;
                    case RELAUNCH_ACTIVITY: {
                    //ignore some code
                    }
    

    从 case LAUNCH_ACTIVITY这可以知道,Activity的启动过程由ActivityThread的handleLaunchActivity实现,源码如下:

      private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
                //ignore some code
            Activity a = performLaunchActivity(r, customIntent);
    
                ...
    
            if (a != null) {
                r.createdConfig = new Configuration(mConfiguration);
               Bundle oldState = r.state;
               handleResumeActivity(r.token, false, r.isForward,
                      !r.activity.mFinished && !r.startsNotResumed);
                ...
    

    从上面源码看出,performLaunchActivity方法最终完成了Activity对象的创建和启动过程,并且ActivityThread通过handleResumeActivity方法来调用被启动Activity的onResume方法,performLaunchActivity这个方法主要完成了如下几件事

    1.从ActivityClientRecord中获取待启动的Activity的组件信息
     ActivityInfo aInfo = r.activityInfo;
            if (r.packageInfo == null) {
               r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                       Context.CONTEXT_INCLUDE_CODE);
           }
    
            ComponentName component = r.intent.getComponent();
           if (component == null) {
                component = r.intent.resolveActivity(
                   mInitialApplication.getPackageManager());
               r.intent.setComponent(component);
           }
    
           if (r.activityInfo.targetActivity != null) {
                component = new ComponentName(r.activityInfo.packageName,
                       r.activityInfo.targetActivity);
           }
    
    2.通过Instrumentation的newActivity方法使用类加载器创建Activity对象
     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);
                }
           }
    

    Instrumentation的newActivity方法,实现比较简单,就是通过类加载器来创建Activity对象:

     public Activity newActivity(ClassLoader cl, String className,
                Intent intent)
             throws InstantiationException, IllegalAccessException,
               ClassNotFoundException {
            return (Activity)cl.loadClass(className).newInstance();
        }
     
    
    3.通过LoadApk的makeApplication方法创建Application对象
    public Application makeApplication(boolean forceDefaultAppClass,
                Instrumentation instrumentation) {
             if (mApplication != null) {
                return mApplication;
            }
    
            Application app = null;
    
            String appClass = mApplicationInfo.className;
             if (forceDefaultAppClass || (appClass == null)) {
                appClass = "android.app.Application";
             }
     
            try {
                java.lang.ClassLoader cl = getClassLoader();
                if (!mPackageName.equals("android")) {
                     initializeJavaContextClassLoader();
                }
                 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
                app = mActivityThread.mInstrumentation.newApplication(
                        cl, appClass, appContext);
                 appContext.setOuterContext(app);
                    ...ignore some code...
    if (instrumentation != null) {
                try {
                    instrumentation.callApplicationOnCreate(app);
                } catch (Exception e) {
                   if (!instrumentation.onException(app, e)) {
                   ...ignore some code...
    

    从makeApplication的实现可以看出,如果Application创建过了,就不会再创建,这也意味着一个应用只有一个Application对象,Application对象也是通过Instrumentation(newApplication)完成的,和newActivity一样,都是通过类加载器实现。Application创建后,系统会通过Instrumentation的callApplicationOnCreate来调用Application的onCreate方法。

    4.创建Context对象并通过Activity的attach方法完成一些重要数据的初始化
     Context appContext = createBaseContextForActivity(r, activity);
                    CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                    Configuration config = new Configuration(mCompatConfiguration);
                   if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                           + r.activityInfo.name + " with config " + config);
                   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);
    
    

    Context是通过Activity的attach方法和Activity关联的,除此之后,在attach中Activity还会完成Window的创建并建立关联,这样当Window接到外部输入事件后就可以将事件传递给Activity。

    5.调用Activity的onCreate方法

    mInstrumentation.callActivityOnCreate(activity, r.state),由于Activity的onCreate已经被调用,这也意味着Activity已经完成了整个启动过程。

    参考文章

    【凯子哥带你学Framework】Activity启动过程全解析

    参考书籍:Android开发艺术探索

    相关文章

      网友评论

        本文标题:Activity启动过程详解

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