美文网首页Android知识
Android学习笔记--Activity启动流程

Android学习笔记--Activity启动流程

作者: gustiness | 来源:发表于2017-07-03 20:55 被阅读0次

    前言

    最近在学习插件化相关的知识,发现自己对安卓Activity的理解还很欠缺,于是写下了这篇博客。

    源码分析

    无论是startActivity和startActivityForResult方法最终都会进入到三个参数的startActivityForResult方法,如下:

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

    实际上,mParent参数一直都是null,所以就会进入就会进入if语句,可以看到,紧接着进入了execStartActivity方法,我们追踪进去看一下:

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

    扫过一遍代码,可以发现 ActivityManagerNative.getDefault().startActivity(...),这里应该就是启动Activity的地方了,由于ActivityManagerNative继承自Binder,实际上startActivity方法应该是在ActivityManagerService中,追下去:

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

    实际上调用的是startActivityAsUser方法:

        @Override
        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) {
            enforceNotIsolatedCaller("startActivity");
            userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                    userId, false, ALLOW_FULL_ONLY, "startActivity", null);
            // TODO: Switch to user app stacks here.
            return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                    resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                    profilerInfo, null, null, bOptions, false, userId, null, null);
        }
    

    中间又经过了一系列方法的传递,这个过程就不再叙述了,就到达了ActivityThread的内部类ApplicationThread的scheduleLaunchActivity方法:

    @Override
            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;
                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;
    
                r.overrideConfig = overrideConfig;
                updatePendingConfiguration(curConfig);
    
                sendMessage(H.LAUNCH_ACTIVITY, r);
            }
    

    大致看一下代码,发现最后一句代码很可能和启动流程相关 于是继续跟进去:

        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();
            msg.what = what;
            msg.obj = obj;
            msg.arg1 = arg1;
            msg.arg2 = arg2;
            if (async) {
                msg.setAsynchronous(true);
            }
            mH.sendMessage(msg);
        }
    

    看了那么多陌生的类名,终于到了我们熟悉的类:Handler,这个Handler能够对非常多的情况处理,这里只列出一部分

    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;
                    case RELAUNCH_ACTIVITY: {
                        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
                        ActivityClientRecord r = (ActivityClientRecord)msg.obj;
                        handleRelaunchActivity(r);
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    } break;
                    case PAUSE_ACTIVITY: {
                        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                        SomeArgs args = (SomeArgs) msg.obj;
                        handlePauseActivity((IBinder) args.arg1, false,
                                (args.argi1 & USER_LEAVING) != 0, args.argi2,
                                (args.argi1 & DONT_REPORT) != 0, args.argi3);
                        maybeSnapshot();
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    } break;
                    case PAUSE_ACTIVITY_FINISHING: {
                        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                        SomeArgs args = (SomeArgs) msg.obj;
                        handlePauseActivity((IBinder) args.arg1, true, (args.argi1 & USER_LEAVING) != 0,
                                args.argi2, (args.argi1 & DONT_REPORT) != 0, args.argi3);
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    } break;
                    case RESUME_ACTIVITY:
                        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
                        SomeArgs args = (SomeArgs) msg.obj;
                        handleResumeActivity((IBinder) args.arg1, true, args.argi1 != 0, true,
                                args.argi3, "RESUME_ACTIVITY");
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                        break;
                    case SEND_RESULT:
                        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult");
                        handleSendResult((ResultData)msg.obj);
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                        break;
                    case DESTROY_ACTIVITY:
                        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
                        handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
                                msg.arg2, false);
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                        break;
                }
                Object obj = msg.obj;
                if (obj instanceof SomeArgs) {
                    ((SomeArgs) obj).recycle();
                }
                if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
            }
    

    第一个case里,进入到了handleLaunchActivity方法:

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
            // If we are getting ready to gc after going to the background, well
            // we are back active so skip it.
            unscheduleGcIdler();
            mSomeActivitiesChanged = true;
    
            if (r.profilerInfo != null) {
                mProfiler.setProfiler(r.profilerInfo);
                mProfiler.startProfiling();
            }
    
            // Make sure we are running with the most recent config.
            handleConfigurationChanged(null, null);
    
            if (localLOGV) Slog.v(
                TAG, "Handling launch of " + r);
    
            // Initialize before creating the activity
            WindowManagerGlobal.initialize();
    
            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);
    
                if (!r.activity.mFinished && r.startsNotResumed) {
                    if (r.isPreHoneycomb()) {
                        r.state = oldState;
                    }
                }
            } else {
                // If there was an error, for any reason, tell the activity manager to stop us.
                try {
                    ActivityManagerNative.getDefault()
                        .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
        }
    

    在这个代码的中间部分,哇,Activity被创建了,终于跟到了.... 那我们就快去看一下performLaunchActivity方法,我们先看一下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);
                }
            }
    

    可以看到activity是被newActivity方法创建的,跟进去看一下:

        public Activity newActivity(ClassLoader cl, String className,
                Intent intent)
                throws InstantiationException, IllegalAccessException,
                ClassNotFoundException {
            return (Activity)cl.loadClass(className).newInstance();
        }
    

    这里就是通过类加载器的loadClass将Activity类加载了进来,然后通过newInstance()方法,创建了一个Activity对象。

    在performLaunchActivity方法中,还创建了Application,代码如下:

           Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    

    跟进makeApplication方法:

            public Application makeApplication(boolean forceDefaultAppClass,
                Instrumentation instrumentation) {
            if (mApplication != null) {
                return mApplication;
            }
    
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
    
            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")) {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                            "initializeJavaContextClassLoader");
                    initializeJavaContextClassLoader();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                }
                ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
                app = mActivityThread.mInstrumentation.newApplication(
                        cl, appClass, appContext);
                appContext.setOuterContext(app);
            } catch (Exception e) {
                if (!mActivityThread.mInstrumentation.onException(app, e)) {
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    throw new RuntimeException(
                        "Unable to instantiate application " + appClass
                        + ": " + e.toString(), e);
                }
            }
            mActivityThread.mAllApplications.add(app);
            mApplication = app;
    
            if (instrumentation != null) {
                try {
                    instrumentation.callApplicationOnCreate(app);
                } catch (Exception e) {
                    if (!instrumentation.onException(app, e)) {
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                        throw new RuntimeException(
                            "Unable to create application " + app.getClass().getName()
                            + ": " + e.toString(), e);
                    }
                }
            }
    
            // Rewrite the R 'constants' for all library apks.
            SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
                    .getAssignedPackageIdentifiers();
            final int N = packageIdentifiers.size();
            for (int i = 0; i < N; i++) {
                final int id = packageIdentifiers.keyAt(i);
                if (id == 0x01 || id == 0x7f) {
                    continue;
                }
    
                rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
            }
    
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    
            return app;
        }
    

    查看中间部分try catch中的代码,可以发现,Application也是通过classloader加载了进来,创建除了Application对象,之后又赋值给了mApplication这个成员变量。所以,除了第一次调用makeApplication外,之后再调用这个方法都会在if(mApplication != null)返回出去,所以,一个应用只有一个Application对象。
    在这段代码的最后一个try catch里,调用了callApplicationOncreate方法,他的实现如下:

        public void callApplicationOnCreate(Application app) {
            app.onCreate();
        }
    

    可以看到,application在这里调用了oncreate方法。

    除此之外,performLaunchActivity创建了context,代码如下:

                    if (activity != null) {
                      Context appContext = createBaseContextForActivity(r, activity);
                      CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                      Configuration config = new Configuration(mCompatConfiguration);
                    if (r.overrideConfig != null) {
                        config.updateFrom(r.overrideConfig);
                    }
                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                            + r.activityInfo.name + " with config " + config);
                    Window window = null;
                    if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                        window = r.mPendingRemoveWindow;
                        r.mPendingRemoveWindow = null;
                        r.mPendingRemoveWindowManager = 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);
    

    发现Context是在createBaseContextForActivity方法里创建出来的,然后在activity的attach方法中,将新创建的context与activity关联了起来。
    然后,调用了Activity的onCreate方法

                    activity.mCalled = false;
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnCreate(activity, r.state);
                    }
    

    到这里,activity的启动流程也就走了一遍,希望你能对Activity多了几分了解~

    相关文章

      网友评论

        本文标题:Android学习笔记--Activity启动流程

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