Android中Activity的啟動流程

個人博客: http://zhangsunyucong.top

前言

在這篇文章中浪册,將會基于android 26源碼上分析Activity從啟動到顯示到屏幕和Decorview添加到Window中的過程。另外在本文中航棱,省略了很多內(nèi)容放祟,目的只是從源碼中找到一條啟動的線索蚂四。遲點再補充上流程圖臣咖。

從startActivity開始說起

在應(yīng)用層開發(fā)時控硼,Acitvity跳轉(zhuǎn)會寫出下面的代碼:

public static void startAtcivity(BaseActivity activity) {
        if(activity != null) {
            Intent intent = new Intent(activity, HomeAcivity.class);
            activity.startActivity(intent);
        }
    }


首先看下activity的繼承關(guān)系:

context繼承關(guān)系
activity繼承關(guān)系

第一張圖,知道activity是context的子類戳杀,第二張圖该面,我們可以知道各種activity的關(guān)系。
另外會寫一片文章信卡,介紹context隔缀。

現(xiàn)在我們進入activity#startActivity

    @Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }
    
    @Override
    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);
        }
    }

接著調(diào)用activity#startActivityForResult

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

在1傍菇、中猾瘸,出現(xiàn)了Instrumentation,并調(diào)用了execStartActivity方法
進入Instrumentation#execStartActivity

    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);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
                        result = am.onStartActivity(intent);
                    }
                    ...
                }
            }
        }
        try {
            ...
            //1、進入ActivityManagerService中
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            //2牵触、檢查創(chuàng)建actiity過程是否產(chǎn)生了異常            
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

在1淮悼、中,出現(xiàn)了ActivityManager揽思。取到IActivityManager袜腥,這里有涉及binder機制,ActivityManager.getService()得到的就是ActivityManagerService钉汗,ActivityManagerService實現(xiàn)了IActivityManager.Stub瞧挤,而ActivityManager中有IActivityManager.Stub.asInterface的遠程調(diào)用。
ActivityManager#getService

    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

   private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

在2儡湾、中特恬,Instrumentation#checkStartActivityResult方法

    /** @hide */
    public static void checkStartActivityResult(int res, Object intent) {
        if (!ActivityManager.isStartResultFatalError(res)) {
            return;
        }

        switch (res) {
            case ActivityManager.START_INTENT_NOT_RESOLVED:
            case ActivityManager.START_CLASS_NOT_FOUND:
                if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                //1、出現(xiàn)沒有注冊異常
                    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);
            case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
                throw new IllegalStateException(
                        "Session calling startVoiceActivity does not match active session");
            case ActivityManager.START_VOICE_HIDDEN_SESSION:
                throw new IllegalStateException(
                        "Cannot start voice activity on a hidden session");
            case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
                throw new IllegalStateException(
                        "Session calling startAssistantActivity does not match active session");
            case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
                throw new IllegalStateException(
                        "Cannot start assistant activity on a hidden session");
            case ActivityManager.START_CANCELED:
                throw new AndroidRuntimeException("Activity could not be started for "
                        + intent);
            default:
                throw new AndroidRuntimeException("Unknown error code "
                        + res + " when starting " + intent);
        }
    }

這是檢查在啟動activity過程中徐钠,可能出現(xiàn)的異常癌刽。比如,啟動的Acitivity沒有在AndroidManifest.xml中注冊尝丐,會出現(xiàn)代碼中1显拜、的異常。

繼續(xù)爹袁,回到在execStartActivity的1远荠、進入ActivityManagerService#startActivity

        @Override
        public int startActivity(IBinder whoThread, String callingPackage,
                Intent intent, String resolvedType, Bundle bOptions) {
            checkCaller();

            int callingUser = UserHandle.getCallingUserId();
            TaskRecord tr;
            IApplicationThread appThread;
            synchronized (ActivityManagerService.this) {
                tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
                if (tr == null) {
                    throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
                }
                //1、IApplicationThread
                appThread = IApplicationThread.Stub.asInterface(whoThread);
                if (appThread == null) {
                    throw new IllegalArgumentException("Bad app thread " + appThread);
                }
            }
            //2失息、ActivityStarter
            return mActivityStarter.startActivityMayWait(appThread, -1, callingPackage, intent,
                    resolvedType, null, null, null, null, 0, 0, null, null,
                    null, bOptions, false, callingUser, null, tr, "AppTaskImpl");
        }

在1譬淳、處,出現(xiàn)了IApplicationThread盹兢,這里涉及到了binder機制邻梆,IApplicationThread的實現(xiàn)是在ActivityThread中的內(nèi)部類ApplicationThread

ActivityThread#ApplicationThread

    private class ApplicationThread extends IApplicationThread.Stub {
      
      ...

        private void updatePendingConfiguration(Configuration config) {
           ...
        }

        public final void schedulePauseActivity(IBinder token, boolean finished,
             ...
        }

        public final void scheduleStopActivity(IBinder token, boolean showWindow,
                int configChanges) {
            ...
        }

        public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {
            ...
        }

       ...
       
        public final void scheduleResumeActivity(IBinder token, int processState,
                boolean isForward, Bundle resumeArgs) {
            ...
        }

        public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
            ...
        }

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

           ...
        }

        @Override
        public final void scheduleRelaunchActivity(IBinder token,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                int configChanges, boolean notResumed, Configuration config,
                Configuration overrideConfig, boolean preserveWindow) {
           ...
        }

        public final void scheduleNewIntent(
                List<ReferrerIntent> intents, IBinder token, boolean andPause) {
            ...
        }

        public final void scheduleDestroyActivity(IBinder token, boolean finishing,
                int configChanges) {
            ...
        }

        public final void scheduleReceiver(Intent intent, ActivityInfo info,
                CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
                boolean sync, int sendingUser, int processState) {
            ...
        }

       ...

        public final void scheduleCreateService(IBinder token,
                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
           ...
        }

        public final void scheduleBindService(IBinder token, Intent intent,
                boolean rebind, int processState) {
            ...
        }

        public final void scheduleUnbindService(IBinder token, Intent intent) {
           ...
        }

        public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
            List<ServiceStartArgs> list = args.getList();
          ...
        }

        public final void scheduleStopService(IBinder token) {
            ...
        }

        public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableBinderTracking, boolean trackAllocation,
                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
                String buildSerial) {
            ...
        }

       ...

        public void scheduleConfigurationChanged(Configuration config) {
            updatePendingConfiguration(config);
            ...
        }

      ...

        public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
                int resultCode, String dataStr, Bundle extras, boolean ordered,
                boolean sticky, int sendingUser, int processState) throws RemoteException {
            ...
        }

       ...

        @Override
        public void scheduleActivityConfigurationChanged(
                IBinder token, Configuration overrideConfig) {
           ...
        }

      ...
    }

在ApplicationThread中浦妄,有很多與Activity剂娄,service,Application生命周期有關(guān)的方法玄呛。
其中scheduleLaunchActivity()應(yīng)該就是負責Activity創(chuàng)建的阅懦。

ActivityManagerService#startActivity的2把鉴、處故黑,調(diào)用了ActivityStarter的startActivityMayWait方法庭砍,它又調(diào)用了startActivityLocked方法

    1场晶、
    int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
           ...

        mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
                container, inTask);

       ...
        return mLastStartActivityResult;
    }
    
    2、
    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
            TaskRecord inTask) {
      ...

        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
                options, inTask, outActivity);
    }
    
    3怠缸、
    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
       ...
        try {
            mService.mWindowManager.deferSurfaceLayout();
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity);
        } finally {
            ...
        }

       ...
        return result;
    }

在3、中揭北,調(diào)用了startActivityUnchecked方法,startActivityUnchecked又調(diào)用了ActivityStackSupervisor#resumeFocusedStackTopActivityLocked方法恨樟,

ActivityStackSupervisor#resumeFocusedStackTopActivityLocked

    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || r.state != RESUMED) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        } else if (r.state == RESUMED) {
            // Kick off any lingering app transitions form the MoveTaskToFront operation.
            mFocusedStack.executeAppTransition(targetOptions);
        }
        return false;
    }

上面方法中疚俱,接著調(diào)用ActivityStack的resumeTopActivityUncheckedLocked方法,
ActivityStack#resumeTopActivityUncheckedLocked

    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
    ...

        return result;
    }

接著調(diào)用resumeTopActivityInnerLocked方法呆奕,在resumeTopActivityInnerLocked中調(diào)用ActivityStackSupervisor的startSpecificActivityLocked方法

ActivityStackSupervisor#startSpecificActivityLocked

    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        ...
        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                   ...
                }
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
               ...
            }

        }

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

方法中調(diào)用了realStartActivityLocked方法梁钾,它里面有下面的代碼:

ActivityStackSupervisor#realStartActivityLocked

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
        System.identityHashCode(r), r.info,
        // TODO: Have this take the merged configuration instead of separate global and
        // override configs.
        mergedConfiguration.getGlobalConfiguration(),
        mergedConfiguration.getOverrideConfiguration(), r.compat,
        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
        r.persistentState, results, newIntents, !andResume,
         mService.isNextTransitionForward(), profilerInfo);

上面的app.thread就是ApplicationThread,并調(diào)用scheduleLaunchActivity。

上面曾經(jīng)說過ApplicationThread是AcitivityThread的內(nèi)部類零酪。

進入ApplicationThread的scheduleLaunchActivity方法拇勃,它最后會發(fā)送一個消息給名為H的handler

sendMessage(H.LAUNCH_ACTIVITY, r);

H.LAUNCH_ACTIVITY的消息處理邏輯是:

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;

調(diào)用handleLaunchActivity方法。在handleLaunchActivity主要是分別調(diào)用performLaunchActivity和handleResumeActivity方法

進入ActivityThread#performLaunchActivity

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
        //1潜秋、收集創(chuàng)建Acitivity的信息
        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        ...

        //2、創(chuàng)建Context的實現(xiàn)者ContextImpl
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            //3罗售、通Instrumentation創(chuàng)建activity
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            ...
        } catch (Exception e) {
            ...
        }

        try {
            //4钩述、創(chuàng)建Application
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

           ...
            if (activity != null) {
                ...
                appContext.setOuterContext(activity);
                //5、調(diào)用activity的attach方法
                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);
                ...
                
               if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                if (r.isPersistable()) {
                    //6牙勘、調(diào)用Activity的OnCreate方法
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }            

                ...
                //7所禀、調(diào)用Activity的OnStart方法
                 if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
                
                ...
            }
            r.paused = true;

            mActivities.put(r.token, r);

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            ...
        }

        return activity;
    }

在3放钦、中,會調(diào)用Instrumentation#newActivity

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

可以看出是通過類加載器通過反射創(chuàng)建Activity實例的操禀。

在4、中斤寂,調(diào)用了LoadedApk#makeApplication方法揪惦,

app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);

makeApplication方法中,和newActivity差不多器腋,也是由Instrumentation的newApplication方法,通過反射創(chuàng)建Application的

5再愈、中調(diào)用Acitivty的attach方法护戳,

Acitivty#attach

    final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        ...
        mUiThread = Thread.currentThread();
        ...
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;

        mWindow.setColorMode(info.colorMode);
    }

在該方法中,主要是會創(chuàng)建PhoneWindow抗悍。

在6和7中钳枕,分別調(diào)用了acitivity的生命周期方法,onCreate和onStart鱼炒。

已經(jīng)分析了在handleLaunchActivity的performLaunchActivity方法。
現(xiàn)在分析handleLaunchActivity的handleResumeActivity指蚁,在handleResumeActivity中會調(diào)用acitivity的生命周期方法onResume和將Decorview添加到Window中自晰,并在makeVisible中顯示出來。

Activity#handleResumeActivity

final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        if (!checkAndUpdateLifecycleSeq(seq, r, "resumeActivity")) {
            return;
        }

        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        //1酬荞、會調(diào)用Acitvity的onResume生命周期方法
        // TODO Push resumeArgs into the activity for consideration
        r = performResumeActivity(token, clearHide, reason);

        if (r != null) {
            final Activity a = r.activity;

            ...
            if (!willBeVisible) {
                try {
                    willBeVisible = ActivityManager.getService().willActivityBeVisible(
                            a.getActivityToken());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                //2、設(shè)置decor不可見
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (r.mPreserveWindow) {
                    a.mWindowAdded = true;
                    r.mPreserveWindow = false;
                    // Normally the ViewRoot sets up callbacks with the Activity
                    // in addView->ViewRootImpl#setView. If we are instead reusing
                    // the decor view we have to notify the view root that the
                    // callbacks may have changed.
                    ViewRootImpl impl = decor.getViewRootImpl();
                    if (impl != null) {
                        impl.notifyChildRebuilt();
                    }
                }
                if (a.mVisibleFromClient) {
                    if (!a.mWindowAdded) {
                        a.mWindowAdded = true;
                        //3勤揩、將Decorviewt添加到Window
                        wm.addView(decor, l);
                    } else {
                        // The activity will get a callback for this {@link LayoutParams} change
                        // earlier. However, at that time the decor will not be set (this is set
                        // in this method), so no action will be taken. This call ensures the
                        // callback occurs with the decor set.
                        a.onWindowAttributesChanged(l);
                    }
                }

            // If the window has already been added, but during resume
            // we started another activity, then don't yet make the
            // window visible.
            } else if (!willBeVisible) {
                if (localLOGV) Slog.v(
                    TAG, "Launch " + r + " mStartedActivity set");
                r.hideForNow = true;
            }

            // Get rid of anything left hanging around.
            cleanUpPendingRemoveWindows(r, false /* force */);

            // The window is now visible if it has been added, we are not
            // simply finishing, and we are not starting another activity.
            if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {
                if (r.newConfig != null) {
                    performConfigurationChangedForActivity(r, r.newConfig);
                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
                            + r.activityInfo.name + " with newConfig " + r.activity.mCurrentConfig);
                    r.newConfig = null;
                }
                if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
                        + isForward);
                WindowManager.LayoutParams l = r.window.getAttributes();
                if ((l.softInputMode
                        & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
                        != forwardBit) {
                    l.softInputMode = (l.softInputMode
                            & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
                            | forwardBit;
                    if (r.activity.mVisibleFromClient) {
                        ViewManager wm = a.getWindowManager();
                        View decor = r.window.getDecorView();
                        wm.updateViewLayout(decor, l);
                    }
                }

                r.activity.mVisibleFromServer = true;
                mNumVisibleActivities++;
                if (r.activity.mVisibleFromClient) {
                    //4、調(diào)用makeVisible
                    r.activity.makeVisible();
                }
            }

            ...

        } else {
           ...
        }
    }

在1凿傅、處的performResumeActivity方法中,會調(diào)用以下代碼:

r.activity.performResume();

即調(diào)用activity的onResume生命周期方法辨液。

在2、中滔迈,設(shè)置了Decorview為不可見
在3被辑、中,將Decorview添加到window中盼理,由于2中設(shè)置了Decorview為不可見,這時view還看不到奏路。
在4臊诊、中,調(diào)用Activity的makeVisible方法抓艳。
Activity#makeVisible

    void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }

上面代碼中,將Decorview設(shè)置為可見的威兜。

剩下問題

在上面過程中的哪里開始涉及視圖繪制。遲點再看椒舵。
分析追溯到Zygote中约谈。
本篇文章的排版還有點亂犁钟。

優(yōu)秀文章:http://blog.csdn.net/dd864140130/article/details/60466394

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末泼橘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子炬灭,更是在濱河造成了極大的恐慌,老刑警劉巖米愿,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鼻吮,死亡現(xiàn)場離奇詭異,居然都是意外死亡椎木,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門漱竖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來畜伐,“玉大人,你說我怎么就攤上這事讼积。” “怎么了勤众?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵鲤脏,是天一觀的道長。 經(jīng)常有香客問我窥突,道長,這世上最難降的妖魔是什么阻问? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任沦疾,我火速辦了婚禮第队,結(jié)果婚禮上刨秆,老公的妹妹穿的比我還像新娘。我一直安慰自己衡未,他們只是感情好,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布如失。 她就那樣靜靜地躺著改衩,像睡著了一般驯镊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上板惑,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天冯乘,我揣著相機與錄音洽胶,去河邊找鬼裆馒。 笑死,一個胖子當著我的面吹牛翔横,可吹牛的內(nèi)容都是我干的梗搅。 我是一名探鬼主播,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼无切,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了掘托?” 一聲冷哼從身側(cè)響起籍嘹,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤沼本,失蹤者是張志新(化名)和其女友劉穎锭沟,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體族淮,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年贴妻,在試婚紗的時候發(fā)現(xiàn)自己被綠了蝙斜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡娩鹉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出弯予,到底是詐尸還是另有隱情个曙,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布呼寸,位于F島的核電站,受9級特大地震影響对雪,放射性物質(zhì)發(fā)生泄漏糟趾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一义郑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧交汤,春花似錦、人聲如沸芙扎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽圈浇。三九已至,卻和暖如春磷蜀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背褐隆。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留衫贬,地道東北人虫埂。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓圃验,卻偏偏與公主長得像,于是被迫代替她去往敵國和親澳窑。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 說到Activity生命周期是不是覺得很簡單鸡捐,在各個生命周期方法中打下log不就知道執(zhí)行的流程了麻裁。但是還是想知道這...
    草貌路飛閱讀 1,364評論 0 0
  • 背景介紹 從事開發(fā)到了一定階段,想要提高就必須搞明白系統(tǒng)的一些工作原理色迂。為什么手销?因為只有明白了這些歇僧,你才能針對平臺...
    CoorChice閱讀 72,705評論 57 508
  • 我認為書就像一艘船诈悍,這和海浪都打不翻它祸轮;我認為書是用也用不完的金子侥钳;我又是書向一個知識淵博的老仙,記載著兩千多...
    5505王妙伊閱讀 171評論 0 1