一 .Android程序流程

众所周知,我们的java程序想要开启需要依赖于main方法,也就是我们的程序入口(主线程)进入,但是在我们日常开发android程序的过程当中我们并没有发现main方法的存在,那么android当中的是如何开始运行的?

熟悉的朋友们可能都知道在android当中存在一个叫做ActivityThread的类,这个类代表的是android当中的主线程,而在这个类当中我们看到了比较熟悉的main方法,那么现在是否可以认为我们的android在打开app时是首先调用的是当前这个类的main,也就是此处为我们的启动点。

ActivityThread#main:

   public static void main(String[] args) {        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");        // CloseGuard defaults to true and can be quite spammy.  We        // disable it here, but selectively enable it later (via        // StrictMode) on debug builds, but using DropBox, not logs.        CloseGuard.setEnabled(false);        Environment.initForCurrentUser();        // Set the reporter for event logging in libcore        EventLogger.setReporter(new EventLoggingReporter());        // Make sure TrustedCertificateStore looks in the right place for CA certificates        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());        TrustedCertificateStore.setDefaultUserDirectory(configDir);        Process.setArgV0("");        Looper.prepareMainLooper();        //1.开启一个Activity线程        ActivityThread thread = new ActivityThread();        //2.调用attach函数        thread.attach(false);        if (sMainThreadHandler == null) {            sMainThreadHandler = thread.getHandler();        }        if (false) {            Looper.myLooper().setMessageLogging(new                    LogPrinter(Log.DEBUG, "ActivityThread"));        }        // End of event ActivityThreadMain.        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);        Looper.loop();        throw new RuntimeException("Main thread loop unexpectedly exited");    }
说明: 在此处可以看到Activity调用了一个attach()方法,ActivityTread#attach:
    private void attach(boolean system) {        sCurrentActivityThread = this;        mSystemThread = system;        if (!system) {            ViewRootImpl.addFirstDrawHandler(new Runnable() {                @Override                public void run() {                    ensureJitEnabled();                }            });            android.ddm.DdmHandleAppName.setAppName("",                                                    UserHandle.myUserId());            RuntimeInit.setApplicationObject(mAppThread.asBinder());            //1.此处调用看到有一个Activity管理窗口            final IActivityManager mgr = ActivityManager.getService();            try {                //2.调用attachApplication绑定mAppThread                mgr.attachApplication(mAppThread);            } catch (RemoteException ex) {                throw ex.rethrowFromSystemServer();            }            ......        } else {            // Don't set application object here -- if the system crashes,            // we can't display an alert, we just want to die die die.            android.ddm.DdmHandleAppName.setAppName("system_process",                    UserHandle.myUserId());            try {                mInstrumentation = new Instrumentation();                ContextImpl context = ContextImpl.createAppContext(                        this, getSystemContext().mPackageInfo);                mInitialApplication = context.mPackageInfo.makeApplication(true, null);                mInitialApplication.onCreate();            } catch (Exception e) {                throw new RuntimeException(                        "Unable to instantiate Application():" + e.toString(), e);            }        }        // add dropbox logging to libcore        DropBox.setReporter(new DropBoxReporter());        ViewRootImpl.ConfigChangedCallback configChangedCallback                = (Configuration globalConfig) -> {            synchronized (mResourcesManager) {                // We need to apply this change to the resources immediately, because upon returning                // the view hierarchy will be informed about it.                if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,                        null /* compat */)) {                    updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),                            mResourcesManager.getConfiguration().getLocales());                    // This actually changed the resources! Tell everyone about it.                    if (mPendingConfiguration == null                            || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {                        mPendingConfiguration = globalConfig;                        sendMessage(H.CONFIGURATION_CHANGED, globalConfig);                    }                }        ViewRootImpl.addConfigCallback(configChangedCallback); }   
说明: ActivityManager#getService:
    public static IActivityManager getService() {        return IActivityManagerSingleton.get();    }    //1.调用了的系统的ActivityManagerService这个服务    private static final Singleton IActivityManagerSingleton =            new Singleton() {                @Override                protected IActivityManager create() {                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);                    final IActivityManager am = IActivityManager.Stub.asInterface(b);                    return am;                }            };

说明:在这里,我们可以联想到,在android当中的binder通信机制,那么实际上我们的ActivityManager是有系统服务所调用管理,并且通过在binder接口当中进行调用,这也是为什么我们讲Activity是跨进程访问的原因。

Activity启动流程详解_第1张图片

那么明白了这个时候能够得到ActivityManager之后,我们接着回到attach当中继续看下去, 这个时候会发现,我们调用了一个attachApplication方法(见图2)这个方法又是干嘛的?attachApplication在这里的作用其实实际上是ActivityThread通过attach获取到,然后将applciationThread将其关联,把activity相关信息存储在applciationThread里面,apllicationThread的类为activity的各种状态做了相对应的准备工作。

Activity启动流程详解_第2张图片

这个时候我们需要关注,ApplicationThread当中做了什么?

当我们打开ApplicationThread中我们会看到一堆的schedule方法,这些方法的名称其实就可以给我们表明,代表的是在执行Activity的某种状态时调用的计划执行方法:

ApplicationThread:

    private class ApplicationThread extends IApplicationThread.Stub {        private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";        private int mLastProcessState = -1;        private void updatePendingConfiguration(Configuration config) {            synchronized (mResourcesManager) {                if (mPendingConfiguration == null ||                        mPendingConfiguration.isOtherSeqNewer(config)) {                    mPendingConfiguration = config;                }            }        }        public final void schedulePauseActivity(IBinder token, boolean finished,                boolean userLeaving, int configChanges, boolean dontReport) {            int seq = getLifecycleSeq();            if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this                    + " operation received seq: " + seq);            sendMessage(                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,                    token,                    (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),                    configChanges,                    seq);        }        public final void scheduleStopActivity(IBinder token, boolean showWindow,                int configChanges) {            int seq = getLifecycleSeq();            if (DEBUG_ORDER) Slog.d(TAG, "stopActivity " + ActivityThread.this                    + " operation received seq: " + seq);            sendMessage(                showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,                token, 0, configChanges, seq);        }        public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {            sendMessage(                showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW,                token);        }        public final void scheduleSleeping(IBinder token, boolean sleeping) {            sendMessage(H.SLEEPING, token, sleeping ? 1 : 0);        }        public final void scheduleResumeActivity(IBinder token, int processState,                boolean isForward, Bundle resumeArgs) {            int seq = getLifecycleSeq();            if (DEBUG_ORDER) Slog.d(TAG, "resumeActivity " + ActivityThread.this                    + " operation received seq: " + seq);            updateProcessState(processState, false);            sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0, 0, seq);        }        public final void scheduleSendResult(IBinder token, List results) {            ResultData res = new ResultData();            res.token = token;            res.results = results;            sendMessage(H.SEND_RESULT, res);        }        // we use token to identify this activity without having to send the        // activity itself back to the activity manager. (matters more with ipc)        @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 pendingResults, List pendingNewIntents,                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {            updateProcessState(procState, false);            1.??            ActivityClientRecord r = new ActivityClientRecord();                 //2.发送一个消息            sendMessage(H.LAUNCH_ACTIVITY, r);        }        @Override        public final void scheduleRelaunchActivity(IBinder token,                List pendingResults, List pendingNewIntents,                int configChanges, boolean notResumed, Configuration config,                Configuration overrideConfig, boolean preserveWindow) {            requestRelaunchActivity(token, pendingResults, pendingNewIntents,                    configChanges, notResumed, config, overrideConfig, true, preserveWindow);        }        public final void scheduleNewIntent(                List intents, IBinder token, boolean andPause) {            NewIntentData data = new NewIntentData();            data.intents = intents;            data.token = token;            data.andPause = andPause;            sendMessage(H.NEW_INTENT, data);        }        public final void scheduleDestroyActivity(IBinder token, boolean finishing,                int configChanges) {            sendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,                    configChanges);        }        public final void scheduleReceiver(Intent intent, ActivityInfo info,                CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,                boolean sync, int sendingUser, int processState) {            updateProcessState(processState, false);            ReceiverData r = new ReceiverData(intent, resultCode, data, extras,                    sync, false, mAppThread.asBinder(), sendingUser);            r.info = info;            r.compatInfo = compatInfo;            sendMessage(H.RECEIVER, r);        }        public final void scheduleCreateBackupAgent(ApplicationInfo app,                CompatibilityInfo compatInfo, int backupMode) {            CreateBackupAgentData d = new CreateBackupAgentData();            d.appInfo = app;            d.compatInfo = compatInfo;            d.backupMode = backupMode;            sendMessage(H.CREATE_BACKUP_AGENT, d);        }        public final void scheduleDestroyBackupAgent(ApplicationInfo app,                CompatibilityInfo compatInfo) {            CreateBackupAgentData d = new CreateBackupAgentData();            d.appInfo = app;            d.compatInfo = compatInfo;            sendMessage(H.DESTROY_BACKUP_AGENT, d);        }        public final void scheduleCreateService(IBinder token,                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {            updateProcessState(processState, false);            CreateServiceData s = new CreateServiceData();            s.token = token;            s.info = info;            s.compatInfo = compatInfo;            sendMessage(H.CREATE_SERVICE, s);        }        public final void scheduleBindService(IBinder token, Intent intent,                boolean rebind, int processState) {            updateProcessState(processState, false);            BindServiceData s = new BindServiceData();            s.token = token;            s.intent = intent;            s.rebind = rebind;            if (DEBUG_SERVICE)                Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="                        + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());            sendMessage(H.BIND_SERVICE, s);        }        public final void scheduleUnbindService(IBinder token, Intent intent) {            BindServiceData s = new BindServiceData();            s.token = token;            s.intent = intent;            sendMessage(H.UNBIND_SERVICE, s);        }        public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {            List list = args.getList();            for (int i = 0; i < list.size(); i++) {                ServiceStartArgs ssa = list.get(i);                ServiceArgsData s = new ServiceArgsData();                s.token = token;                s.taskRemoved = ssa.taskRemoved;                s.startId = ssa.startId;                s.flags = ssa.flags;                s.args = ssa.args;                sendMessage(H.SERVICE_ARGS, s);            }        }        public final void scheduleStopService(IBinder token) {            sendMessage(H.STOP_SERVICE, token);        }        public final void bindApplication(String processName, ApplicationInfo appInfo,                List 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) {            if (services != null) {                // Setup the service cache in the ServiceManager                ServiceManager.initServiceCache(services);            }            setCoreSettings(coreSettings);            //...........................            sendMessage(H.BIND_APPLICATION, data);        }      
  //.....

接下来我们看看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 pendingResults, List pendingNewIntents,                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {            updateProcessState(procState, false);            //1.这个对象其实实际上就是我们的Activity            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);            //2.将当前创建的Activity发送了出去            sendMessage(H.LAUNCH_ACTIVITY, r);        }

说明:该方法其实会被系统程序调用。

ActivityThread#sendMessage:

    private void sendMessage(int what, Object obj) {        sendMessage(what, obj, 0, 0, false);    }

继续:

    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);        }        1.H对象实例继承Handle        mH.sendMessage(msg);    }

继续查看H的handleMessage的方法:

 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);                    //1.调用handleLaunchActivity函数启动一个Activity。                    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);                    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 STOP_ACTIVITY_SHOW: {                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");                    SomeArgs args = (SomeArgs) msg.obj;                    handleStopActivity((IBinder) args.arg1, true, args.argi2, args.argi3);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                } break;                case STOP_ACTIVITY_HIDE: {                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");                    SomeArgs args = (SomeArgs) msg.obj;                    handleStopActivity((IBinder) args.arg1, false, args.argi2, args.argi3);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                } break;                case SHOW_WINDOW:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityShowWindow");                    handleWindowVisibility((IBinder)msg.obj, true);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case HIDE_WINDOW:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityHideWindow");                    handleWindowVisibility((IBinder)msg.obj, false);                    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;//.................}

说明:当走到这里我们会发现最终我们调用的是Handler的消息通信机制,也就是说,在这里我们可以总结一下:

(1)当Activity状态改变时,都会有对应的一个消息发送出去,而接收这里,我能发现通过发送时不同的状态,这边调用了不同的handlerXXXActivity方法.

(2)Application运行的过程当中,对于Activity的操作,状态转变,其实实际上是通过Handler消息机制来完成的;

(3)Application当中只管去发, 由消息机制负责调用,因为在main方法当中我门的Looper轮训器是一直在进行轮训的;

继续查看ActivityThread#handlerLaunchActivity方法:

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);        //...........        WindowManagerGlobal.initialize();        //1.调用performLaunchActivity函数new一个Activity实例。        Activity a = performLaunchActivity(r, customIntent);        if (a != null) {            r.createdConfig = new Configuration(mConfiguration);            reportSizeConfigurations(r);            Bundle oldState = r.state;            //2.调用handleResumeActivity,在这个函数中最终进行了View的定位、测量、绘制等操作。            handleResumeActivity(r.token, false, r.isForward,                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);            if (!r.activity.mFinished && r.startsNotResumed) {                // The activity manager actually wants this one to start out paused, because it                // needs to be visible but isn't in the foreground. We accomplish this by going                // through the normal startup (because activities expect to go through onResume()                // the first time they run, before their window is displayed), and then pausing it.                // However, in this case we do -not- need to do the full pause cycle (of freezing                // and such) because the activity manager assumes it can just retain the current                // state it has.                performPauseActivityIfNeeded(r, reason);                // We need to keep around the original state, in case we need to be created again.                // But we only do this for pre-Honeycomb apps, which always save their state when                // pausing, so we can not have them save their state when restarting from a paused                // state. For HC and later, we want to (and can) let the state be saved as the                // normal part of stopping the activity.                if (r.isPreHoneycomb()) {                    r.state = oldState;                }            }        } else {            // If there was an error, for any reason, tell the activity manager to stop us.            try {                ActivityManager.getService()                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);            } catch (RemoteException ex) {                throw ex.rethrowFromSystemServer();            }        }    }

说明:而当我们在加载Activity的时候,当中调用了一个performLaunchActivity()方法,在这个中间我发现了我们onCreate的调用痕迹。

继续查看ActivityThread#performLaunchActivity方法:

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {        //..............        ContextImpl appContext = createBaseContextForActivity(r);        Activity activity = null;        try {            java.lang.ClassLoader cl = appContext.getClassLoader();//1.通过类加载器,new一个Activity实例对象            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) {                //..............        }        try {            Application app = r.packageInfo.makeApplication(false, mInstrumentation);            if (activity != null) {                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());                Configuration config = new Configuration(mCompatConfiguration);                if (r.overrideConfig != null) {                    config.updateFrom(r.overrideConfig);                }                Window window = null;                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {                    window = r.mPendingRemoveWindow;                    r.mPendingRemoveWindow = null;                    r.mPendingRemoveWindowManager = null;                }                appContext.setOuterContext(activity);                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 (customIntent != null) {                    activity.mIntent = customIntent;                }                r.lastNonConfigurationInstances = null;                checkAndBlockForNetworkAccess();                activity.mStartedActivity = false;                int theme = r.activityInfo.getThemeResource();                if (theme != 0) {                    activity.setTheme(theme);                }                activity.mCalled = false;                if (r.isPersistable()) {    //2.调用Activity的onCreate函数                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);                } else {                    mInstrumentation.callActivityOnCreate(activity, r.state);                }                if (!activity.mCalled) {                    throw new SuperNotCalledException(                        "Activity " + r.intent.getComponent().toShortString() +                        " did not call through to super.onCreate()");                }                //...............            }            r.paused = true;            mActivities.put(r.token, r);        } catch (SuperNotCalledException e) {            throw e;        } catch (Exception e) {           }        return activity;    }

说明:也就是说,到目前为止我们能够明白,整个Application加载Activity的整套流程是怎么回事,那么接下来我们需要关注的是,在onCreate当中我们所写的setContentView到底干了什么。

二.setContentView

     在onCreate当中我们往往会使用setContentView去进行设置我们自己的布局文件或者view,那么在这当中他到底是怎么做的?通过观察源码,这个时候通过一系列线索我找到了最终的位置PhoneWindow类。

PhoneWindow#setContentView:

    @Override    public void setContentView(int layoutResID) {        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window        // decor, when theme attributes and the like are crystalized. Do not check the feature        // before this happens.        if (mContentParent == null) {            installDecor();//1.调用该方法加载DecorView(顶层VIew)        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {            mContentParent.removeAllViews();        }        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,                    getContext());            transitionTo(newScene);        } else {//2.加载自己的布局            mLayoutInflater.inflate(layoutResID, mContentParent);        }        mContentParent.requestApplyInsets();        final Callback cb = getCallback();        if (cb != null && !isDestroyed()) {            cb.onContentChanged();        }        mContentParentExplicitlySet = true;    }

说明,这个时候我们会看到他做了两个事情,一个是installDecor,另一个是inflate,这两个后一个不难猜出他是在进行布局文件的解析, 前面的我们认为她是在初始化DecorView。

再看installDecor方法:

    private void installDecor() {        mForceDecorInstall = false;        if (mDecor == null) {//1.如果mDecor为null,那么就调用generateDecor,mDecor代表的是顶层view            mDecor = generateDecor(-1);            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);            mDecor.setIsRootNamespace(true);            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);            }        } else {            mDecor.setWindow(this);        }        if (mContentParent == null) {//2.如果mContentParent为null,调用generateLayout函数生成一个mContentParent            mContentParent = generateLayout(mDecor);            // Set up decor part of UI to ignore fitsSystemWindows if appropriate.            mDecor.makeOptionalFitsSystemWindows();            final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(                    R.id.decor_content_parent);            if (decorContentParent != null) {                mDecorContentParent = decorContentParent;                mDecorContentParent.setWindowCallback(getCallback());                if (mDecorContentParent.getTitle() == null) {                    mDecorContentParent.setWindowTitle(mTitle);                }                final int localFeatures = getLocalFeatures();                for (int i = 0; i < FEATURE_MAX; i++) {                    if ((localFeatures & (1 << i)) != 0) {                        mDecorContentParent.initFeature(i);                    }                }                mDecorContentParent.setUiOptions(mUiOptions);                if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0 ||                        (mIconRes != 0 && !mDecorContentParent.hasIcon())) {                    mDecorContentParent.setIcon(mIconRes);                } else if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) == 0 &&                        mIconRes == 0 && !mDecorContentParent.hasIcon()) {                    mDecorContentParent.setIcon(                            getContext().getPackageManager().getDefaultActivityIcon());                    mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON_FALLBACK;                }                if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0 ||                        (mLogoRes != 0 && !mDecorContentParent.hasLogo())) {                    mDecorContentParent.setLogo(mLogoRes);                }                // Invalidate if the panel menu hasn't been created before this.                // Panel menu invalidation is deferred avoiding application onCreateOptionsMenu                // being called in the middle of onCreate or similar.                // A pending invalidation will typically be resolved before the posted message                // would run normally in order to satisfy instance state restoration.                PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);                if (!isDestroyed() && (st == null || st.menu == null) && !mIsStartingWindow) {                    invalidatePanelMenu(FEATURE_ACTION_BAR);                }            } else {                mTitleView = findViewById(R.id.title);                if (mTitleView != null) {                    if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {                        final View titleContainer = findViewById(R.id.title_container);                        if (titleContainer != null) {                            titleContainer.setVisibility(View.GONE);                        } else {                            mTitleView.setVisibility(View.GONE);                        }                        mContentParent.setForeground(null);                    } else {                        mTitleView.setText(mTitle);                    }                }            }             //........................            }        }    }

mDecor成员变量:

    // This is the top-level view of the window, containing the window decor.    private DecorView mDecor;//这是窗口内容放置的视图

mContentParent变量:

    // This is the view in which the window contents are placed. It is either    // mDecor itself, or a child of mDecor where the contents go.    ViewGroup mContentParent;//这是窗口内容放置的视图,它要么是mDecor本身,要么是mDecor的子类的内容。

继续,generateLayout方法:

 protected ViewGroup generateLayout(DecorView decor) {        // Apply data from current theme.        TypedArray a = getWindowStyle();        mIsFloating = a.getBoolean(R.styleable.Window_windowIsFloating, false);        int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)                & (~getForcedWindowFlags());        if (mIsFloating) {            setLayout(WRAP_CONTENT, WRAP_CONTENT);            setFlags(0, flagsToUpdate);        } else {            setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);        }        if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {            requestFeature(FEATURE_NO_TITLE);        } else if (a.getBoolean(R.styleable.Window_windowActionBar, false)) {            // Don't allow an action bar if there is no title.            requestFeature(FEATURE_ACTION_BAR);        }        if (a.getBoolean(R.styleable.Window_windowActionBarOverlay, false)) {            requestFeature(FEATURE_ACTION_BAR_OVERLAY);        }        if (a.getBoolean(R.styleable.Window_windowActionModeOverlay, false)) {            requestFeature(FEATURE_ACTION_MODE_OVERLAY);        }        if (a.getBoolean(R.styleable.Window_windowSwipeToDismiss, false)) {            requestFeature(FEATURE_SWIPE_TO_DISMISS);        }        if (a.getBoolean(R.styleable.Window_windowFullscreen, false)) {            setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN & (~getForcedWindowFlags()));        }        if (a.getBoolean(R.styleable.Window_windowTranslucentStatus,                false)) {            setFlags(FLAG_TRANSLUCENT_STATUS, FLAG_TRANSLUCENT_STATUS                    & (~getForcedWindowFlags()));        }        if (a.getBoolean(R.styleable.Window_windowTranslucentNavigation,                false)) {            setFlags(FLAG_TRANSLUCENT_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION                    & (~getForcedWindowFlags()));        }        if (a.getBoolean(R.styleable.Window_windowOverscan, false)) {            setFlags(FLAG_LAYOUT_IN_OVERSCAN, FLAG_LAYOUT_IN_OVERSCAN&(~getForcedWindowFlags()));        }        if (a.getBoolean(R.styleable.Window_windowShowWallpaper, false)) {            setFlags(FLAG_SHOW_WALLPAPER, FLAG_SHOW_WALLPAPER&(~getForcedWindowFlags()));        }        if (a.getBoolean(R.styleable.Window_windowEnableSplitTouch,                getContext().getApplicationInfo().targetSdkVersion                        >= android.os.Build.VERSION_CODES.HONEYCOMB)) {            setFlags(FLAG_SPLIT_TOUCH, FLAG_SPLIT_TOUCH&(~getForcedWindowFlags()));        }        a.getValue(R.styleable.Window_windowMinWidthMajor, mMinWidthMajor);        a.getValue(R.styleable.Window_windowMinWidthMinor, mMinWidthMinor);        if (DEBUG) Log.d(TAG, "Min width minor: " + mMinWidthMinor.coerceToString()                + ", major: " + mMinWidthMajor.coerceToString());        if (a.hasValue(R.styleable.Window_windowFixedWidthMajor)) {            if (mFixedWidthMajor == null) mFixedWidthMajor = new TypedValue();            a.getValue(R.styleable.Window_windowFixedWidthMajor,                    mFixedWidthMajor);        }        if (a.hasValue(R.styleable.Window_windowFixedWidthMinor)) {            if (mFixedWidthMinor == null) mFixedWidthMinor = new TypedValue();            a.getValue(R.styleable.Window_windowFixedWidthMinor,                    mFixedWidthMinor);        }        if (a.hasValue(R.styleable.Window_windowFixedHeightMajor)) {            if (mFixedHeightMajor == null) mFixedHeightMajor = new TypedValue();            a.getValue(R.styleable.Window_windowFixedHeightMajor,                    mFixedHeightMajor);        }        if (a.hasValue(R.styleable.Window_windowFixedHeightMinor)) {            if (mFixedHeightMinor == null) mFixedHeightMinor = new TypedValue();            a.getValue(R.styleable.Window_windowFixedHeightMinor,                    mFixedHeightMinor);        }       //............        mDecor.finishChanging();        return contentParent;    }

说明,发现了在此处进行了大量的requestFeature的调用,也就是所,我们的requestFeature。

接着在这个方法中我们又发现:

        int layoutResource;        int features = getLocalFeatures();        // System.out.println("Features: 0x" + Integer.toHexString(features));        if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {            layoutResource = R.layout.screen_swipe_dismiss;            setCloseOnSwipeEnabled(true);        } else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {            if (mIsFloating) {                TypedValue res = new TypedValue();                getContext().getTheme().resolveAttribute(                        R.attr.dialogTitleIconsDecorLayout, res, true);                layoutResource = res.resourceId;            } else {                layoutResource = R.layout.screen_title_icons;            }            // XXX Remove this once action bar supports these features.            removeFeature(FEATURE_ACTION_BAR);            // System.out.println("Title Icons!");        } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0                && (features & (1 << FEATURE_ACTION_BAR)) == 0) {            // Special case for a window with only a progress bar (and title).            // XXX Need to have a no-title version of embedded windows.            layoutResource = R.layout.screen_progress;            // System.out.println("Progress!");        } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {            // Special case for a window with a custom title.            // If the window is floating, we need a dialog layout            if (mIsFloating) {                TypedValue res = new TypedValue();                getContext().getTheme().resolveAttribute(                        R.attr.dialogCustomTitleDecorLayout, res, true);                layoutResource = res.resourceId;            } else {                layoutResource = R.layout.screen_custom_title;            }            // XXX Remove this once action bar supports these features.            removeFeature(FEATURE_ACTION_BAR);        } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {            // If no other features and not embedded, only need a title.            // If the window is floating, we need a dialog layout            if (mIsFloating) {                TypedValue res = new TypedValue();                getContext().getTheme().resolveAttribute(                        R.attr.dialogTitleDecorLayout, res, true);                layoutResource = res.resourceId;            } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {                layoutResource = a.getResourceId(                        R.styleable.Window_windowActionBarFullscreenDecorLayout,                        R.layout.screen_action_bar);            } else {                layoutResource = R.layout.screen_title;            }            // System.out.println("Title!");        } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {            layoutResource = R.layout.screen_simple_overlay_action_mode;        } else {            // Embedded, so no decoration is needed.            layoutResource = R.layout.screen_simple;            // System.out.println("Simple!");        }
        mDecor.startChanging();        mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);//调用onResourceLoaded函数

说明,根据不同的features加载不同的布局,在这里我们只参看其中的一个布局screen_simple.xml:

                    

feature属性一般是在Activity的onCreate方法中,且在setContentView方法之前进行设置,如设置全屏:

        this.requestWindowFeature(Window.FEATURE_NO_TITLE);        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,                WindowManager.LayoutParams.FLAG_FULLSCREEN);

DecorView层级关系,如图:

Activity启动流程详解_第3张图片


继续查看onResourceLoaded:

    void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {        mStackId = getStackId();        if (mBackdropFrameRenderer != null) {            loadBackgroundDrawablesIfNeeded();            mBackdropFrameRenderer.onResourcesLoaded(                    this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,                    mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState),                    getCurrentColor(mNavigationColorViewState));        }        mDecorCaptionView = createDecorCaptionView(inflater);        final View root = inflater.inflate(layoutResource, null);        if (mDecorCaptionView != null) {            if (mDecorCaptionView.getParent() == null) {                addView(mDecorCaptionView,                        new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));            }            mDecorCaptionView.addView(root,                    new ViewGroup.MarginLayoutParams(MATCH_PARENT, MATCH_PARENT));        } else {            // Put it below the color views.            addView(root, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));        }        mContentRoot = (ViewGroup) root;        initializeElevation();    }

然后我们在回到setContentView函数中,在标注2调用inflate加载自己的布局:

    /**     * 从指定的视图当中获取视图的层次结构,意思就是,现在在加载自己的资源)     * Inflate a new view hierarchy from the specified xml node. Throws     * {@link InflateException} if there is an error. *     * 

* Important   For performance * reasons, view inflation relies heavily on pre-processing of XML files * that is done at build time. Therefore, it is not currently possible to * use LayoutInflater with an XmlPullParser over a plain XML file at runtime. * * @param parser XML dom node containing the description of the view * hierarchy. * @param root Optional view to be the parent of the generated hierarchy. * @return The root View of the inflated hierarchy. If root was supplied, * this is the root View; otherwise it is the root of the inflated * XML file. */ public View inflate(XmlPullParser parser, @Nullable ViewGroup root) { return inflate(parser, root, root != null); }

继续inflate函数:

    public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {        final Resources res = getContext().getResources();        //1.获取xml解析工具类        final XmlResourceParser parser = res.getLayout(resource);        try {            return inflate(parser, root, attachToRoot);        } finally {            parser.close();        }    }

继续inflate函数:

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {        synchronized (mConstructorArgs) {            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");            final Context inflaterContext = mContext;            final AttributeSet attrs = Xml.asAttributeSet(parser);            Context lastContext = (Context) mConstructorArgs[0];            mConstructorArgs[0] = inflaterContext;            View result = root;            try {                // Look for the root node.                int type;                //第一步:循环查找root标签                while ((type = parser.next()) != XmlPullParser.START_TAG &&                        type != XmlPullParser.END_DOCUMENT) {                    // Empty                }                //循环结束,没有找到root标签,抛出异常                if (type != XmlPullParser.START_TAG) {                    throw new InflateException(parser.getPositionDescription()                            + ": No start tag found!");                }                //获取标签名                final String name = parser.getName();                // 第二步:判断是否此标签是否为merge,如果是的调用rInflate进一步解析,如果不是的就调用createViewFromTag创建一个View                if (TAG_MERGE.equals(name)) {                    if (root == null || !attachToRoot) {                        throw new InflateException(" can be used only with a valid "                                + "ViewGroup root and attachToRoot=true");                    }                    rInflate(parser, root, inflaterContext, attrs, false);                } else {                    // Temp is the root view that was found in the xml                    final View temp = createViewFromTag(root, name, inflaterContext, attrs);                    ViewGroup.LayoutParams params = null;                    if (root != null) {                                              // Create layout params that match root, if supplied                        params = root.generateLayoutParams(attrs);                        if (!attachToRoot) {                            // Set the layout params for temp if we are not                            // attaching. (If we are, we use addView, below)                            temp.setLayoutParams(params);                        }                    }                    //第三步:解析root的子View                    // Inflate all children under temp against its context.                    rInflateChildren(parser, temp, attrs, true);                    //第四步:调用addView函数,把整个xml资源布局添加到DecorView的id为Content的节点上。                    // We are supposed to attach all the views we found (int temp)                    // to root. Do that now.                    if (root != null && attachToRoot) {                        root.addView(temp, params);                    }                    // Decide whether to return the root that was passed in or the                    // top view found in xml.                    if (root == null || !attachToRoot) {                        result = temp;                    }                }            } catch (XmlPullParserException e) {            } catch (Exception e) {                         } finally {            }            return result;        }    }

流程如下:

Activity启动流程详解_第4张图片

那么在这里我门就能够明白,setContentView其实做了两件比较核心的事情,就是加载环境配置,和自己的布局,那么接下来我门需要考虑的事情就是,他到底怎么画到界面上的。

三 UI是如何绘制的

      在ActivityThread启动时, 我发现在加载handleLaunchActivity方法调用performLaunchActivity方法之后又调用了一个handleResumeActivity在这里我发现了绘制流程的开始。

      回到继续查看ActivityThread#handlerLaunchActivity函数标注2的地方调用了handleResumeActivity函数:

 handleResumeActivity(r.token, false, r.isForward,                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

继续查看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 (r != null) {            final Activity a = r.activity;            final int forwardBit = isForward ?                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;            // If the window hasn't yet been added to the window manager,            // and this guy didn't finish itself or start another activity,            // then go ahead and add the window.            boolean willBeVisible = !a.mStartedActivity;            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();                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;//调用addView函数                        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;            }           //. . . .             } else {            // If an exception was thrown when trying to resume, then            // just end this activity.            try {                ActivityManager.getService()                    .finishActivity(token, Activity.RESULT_CANCELED, null,                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);            } catch (RemoteException ex) {                throw ex.rethrowFromSystemServer();            }        }    }


说明,通过前面的流程我门知道,onCreate之行完成之后,所有资源交给WindowManager保管,在这里,将我们的VIew交给了WindowManager,此处调用了addView。

Activity启动流程详解_第5张图片

继续来看WindowManagerGlobal的addView函数:

public void addView(View view, ViewGroup.LayoutParams params,            Display display, Window parentWindow) {      //.............        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;        if (parentWindow != null) {            parentWindow.adjustLayoutParamsForSubWindow(wparams);        } else {            // If there's no parent, then hardware acceleration for this view is            // set from the application's hardware acceleration setting.            final Context context = view.getContext();            if (context != null                    && (context.getApplicationInfo().flags                            & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {                wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;            }        }        ViewRootImpl root;        View panelParentView = null;        synchronized (mLock) {            // Start watching for system property changes.            if (mSystemPropertyUpdater == null) {                mSystemPropertyUpdater = new Runnable() {                    @Override public void run() {                        synchronized (mLock) {                            for (int i = mRoots.size() - 1; i >= 0; --i) {                                mRoots.get(i).loadSystemProperties();                            }                        }                    }                };                SystemProperties.addChangeCallback(mSystemPropertyUpdater);            }            int index = findViewLocked(view, false);            if (index >= 0) {                if (mDyingViews.contains(view)) {                    // Don't wait for MSG_DIE to make it's way through root's queue.                    mRoots.get(index).doDie();                } else {                    throw new IllegalStateException("View " + view                            + " has already been added to the window manager.");                }                // The previous removeView() had not completed executing. Now it has.            }            // If this is a panel window, then find the window it is being            // attached to for future reference.            if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&                    wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {                final int count = mViews.size();                for (int i = 0; i < count; i++) {                    if (mRoots.get(i).mWindow.asBinder() == wparams.token) {                        panelParentView = mViews.get(i);                    }                }            }            root = new ViewRootImpl(view.getContext(), display);            view.setLayoutParams(wparams);           //把view、root、wparams保存到集合中            mViews.add(view);            mRoots.add(root);            mParams.add(wparams);            // do this last because it fires off messages to start doing things            try {//调用root的setView函数。                root.setView(view, wparams, panelParentView);            } catch (RuntimeException e) {                // BadTokenException or InvalidDisplayException, clean up.                if (index >= 0) {                    removeViewLocked(index, true);                }                throw e;            }        }    }

说明,mViews、mRoots、mParams成员变量。

    //保存的是View对象,DecorView    private final ArrayList mViews = new ArrayList();    //保存和顶层View关联的ViewRootImpl对象    private final ArrayList mRoots = new ArrayList();    //保存的是创建顶层View的layout参数。    private final ArrayList mParams = new ArrayList();

说明,进入addView之后我们发现了一段这样的代码,他将视图,和参数还有我门的一个ViewRoot对象都用了容器去装在了起来,那么在此处我门可以得出,是将所有的相关对象保存起来,而WindowManagerGlobal类也负责和WMS通信,而在此时,有一句关键代码root.setView,这里是将我们的参数,和视图同时交给了ViewRoot,那么这个时候我们来看下ViewRoot当中的setView干了什么。

 public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {        synchronized (this) {            if (mView == null) {                mView = view;               //...............                requestLayout();                //...............                //在这里我门会看到view.assignParent的设置是this, 那么也就是说在view当中parent其实实际上是ViewRoot,                // 那么在setContentView当中调用了一个setLayoutParams()是调用的ViewRoot的setLayoutParams(),                // 而在ViewRoot当中发现了setLayoutParams和preformLayout对requestLayout方法的调用,                // 在requestLayout当中发现了对scheduleTraversals方法的调用                // 而scheduleTraversals当中调用了doTraversal的访问,最终访问到了performTraversals(),                // 而在这个里面,我发现了整体的绘制流程的调用                view.assignParent(this);                //...............            }        }    }

继续scheduleTraversals函数:

    void scheduleTraversals() {        if (!mTraversalScheduled) {            mTraversalScheduled = true;            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();            mChoreographer.postCallback(// mTraversalRunnable 实现Runnable对象,run方法中调用了doTraversal                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);            if (!mUnbufferedInputDispatch) {                scheduleConsumeBatchedInput();            }            notifyRendererOfFramePending();            pokeDrawLockIfNeeded();        }    }

继续查看doTraversal:

    final class TraversalRunnable implements Runnable {        @Override        public void run() {            doTraversal();        }    }
    void doTraversal() {        if (mTraversalScheduled) {            mTraversalScheduled = false;            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);            if (mProfile) {                Debug.startMethodTracing("ViewAncestor");            }           //调用performTraversals函数            performTraversals();            if (mProfile) {                Debug.stopMethodTracing();                mProfile = false;            }        }    }
继续performTraversals函数:
private void performTraversals() {       if (!mStopped || mReportNextDraw) {                boolean focusChangedDueToTouchMode = ensureTouchModeLocally(                        (relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);                if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()                        || mHeight != host.getMeasuredHeight() || contentInsetsChanged ||                        updatedConfiguration) {                    int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);                    int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);                     // 测量操作                    performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);                    //................                }            }        } else {              //................        }  //................} if (didLayout) {    //定位    performLayout(lp, mWidth, mHeight);//................ } //................ //绘制 performDraw();//................}












更多相关文章

  1. C语言函数以及函数的使用
  2. 【Android 内存优化】Bitmap 长图加载 ( BitmapRegionDecoder 简
  3. Android 虚化图片的方法
  4. android完全退出程序的方法
  5. android常用方法汇总-更新中
  6. Android结束进程的方法
  7. Android 比Timer更好方法
  8. Android中AppWidget使用方法
  9. Android 官方 Lambda支持方法

随机推荐

  1. Android(安卓)ImageView 的scaleType属性
  2. Android学习——TextView 设置中划线 下
  3. Port SDL/TinySDGL to android with nati
  4. Android(安卓)Service总结02 service介绍
  5. android merge和include简单使用
  6. 安卓,rebuild apk错误解决
  7. Android(安卓)的提权 (root) 原理是什么?
  8. xml中设置圆角矩形框
  9. Android中Activity启动模式launchermode
  10. 三个博客和一张关系图,掌握Android(安卓)W