Androidソース分析のActivity起動とViewの描画プロセス(一)

26769 ワード

私たちはAppが作成プロセスから実行ActivityThreadまでのプロセスを把握しました。続いてActivityの起動過程を研究します。
ActivityThread铅handleLaunchActivityから言います。
Activityの実用化はActivityThread((zhi handleLaunchActivity)において行われ、関連コードは以下の通りである。
/fram eworks/base/core/java/android/ap/ActivityThread.java
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    ...
    //   Activity,       
    Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        ...
        // resume
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

        ...
    } else {
        ...
    }
}
ActivityのonCreateとonStartは全部performLaunchActivity方法で完成しました。コードは以下の通りです。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...

    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        ...
    } catch (Exception e) {
        ...
    }

    try {
        ...

        if (activity != null) {
            // Activity  Context       
            Context appContext = createBaseContextForActivity(r, activity);
            ...

            //       attach 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);

            ...

            activity.mCalled = false;
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                //   onCreate
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            ...
            if (!r.activity.mFinished) {
                //   onStart
                activity.performStart();
                r.stopped = false;
            }
            if (!r.activity.mFinished) {
                if (r.isPersistable()) {
                    if (r.state != null || r.persistentState != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                r.persistentState);
                    }
                } else if (r.state != null) {
                    //        
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                }
            }
            if (!r.activity.mFinished) {
                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state,
                            r.persistentState);
                } else {
                    //   onPostCreate
                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
                }
                ...
            }
        }
        r.paused = true;

        mActivities.put(r.token, r);

    } catch (SuperNotCalledException e) {
        ...
    }

    return activity;
}
ここではまずActivity atach方法を実行しました。コードは以下の通りです。
/fram eworks/base/core/java/android/ap/Activity.java
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) {
    attachBaseContext(context);

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

    //     Window
    mWindow = new PhoneWindow(this, window);
    mWindow.setWindowControllerCallback(this);
    mWindow.setCallback(this);
    mWindow.setOnWindowDismissedCallback(this);
    mWindow.getLayoutInflater().setPrivateFactory(this);
    if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
        mWindow.setSoftInputMode(info.softInputMode);
    }
    if (info.uiOptions != 0) {
        mWindow.setUiOptions(info.uiOptions);
    }
    mUiThread = Thread.currentThread();

    mMainThread = aThread;
    mInstrumentation = instr;
    mToken = token;
    mIdent = ident;
    mApplication = application;
    mIntent = intent;
    mReferrer = referrer;
    mComponent = intent.getComponent();
    mActivityInfo = info;
    mTitle = title;
    mParent = parent;
    mEmbeddedID = id;
    mLastNonConfigurationInstances = lastNonConfigurationInstances;
    if (voiceInteractor != null) {
        if (lastNonConfigurationInstances != null) {
            mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
        } else {
            mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                    Looper.myLooper());
        }
    }

    //  Window  WindowManager,        
    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の初期化とWindowManagerの構成に注目しています。mWindowはPhone Windowの一例です。ここではパラメータwindowは現在nullです。その構造方法は以下の通りです。
//fram eworks/base/core/java/com/android/internal/policy/Phone Window.java
public PhoneWindow(Context context, Window preservedWindow) {
    this(context);
    // Only main activity windows use decor context, all the other windows depend on whatever
    // context that was given to them.
    mUseDecorContext = true;
    if (preservedWindow != null) {
        //   preservedWindow   ,mDecor      ,       
        mDecor = (DecorView) preservedWindow.getDecorView();
        ...
    }
    ...
}
この時、Phone Windowを作成しただけです。mDecorはまだ空です。WindowManagerはシステムサービスであり、通信方式は依然としてBinderであり、ここでは追跡せず、取得後、mWindow.set Window Manager方法で設定を完了しました。コードは以下の通りです。
// /frameworks/base/core/java/android/view/Window.java
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
        boolean hardwareAccelerated) {
    ...
    mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}

// /frameworks/base/core/java/android/view/WindowManagerImpl.java
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
    return new WindowManagerImpl(mContext, parentWindow);
}
最終的にmwindowオブジェクトに設定されているWindowManagerはWindowManager Implの例です。
引き続きActivityThread((CyperformLaunchActivity)に戻ります。次はmInstructiventation.callActivity OneCreate(activity,r.state)の方法です。コードは以下の通りです。
/frame eworks/base/core/java/android/ap/Instructionation.java
public void callActivityOnCreate(Activity activity, Bundle icicle) {
    prePerformCreate(activity);
    activity.performCreate(icicle);
    postPerformCreate(activity);
}
/fram eworks/base/core/java/android/ap/Activity.java
final void performCreate(Bundle icicle) {
    restoreHasCurrentPermissionRequest(icicle);
    onCreate(icicle);
    mActivityTransitionState.readState(icicle);
    performCreateCommon();
}

protected void onCreate(@Nullable Bundle savedInstanceState) {
    if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
    if (mLastNonConfigurationInstances != null) {
        mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);
    }
    if (mActivityInfo.parentActivityName != null) {
        if (mActionBar == null) {
            mEnableDefaultActionBarUp = true;
        } else {
            mActionBar.setDefaultDisplayHomeAsUpEnabled(true);
        }
    }
    if (savedInstanceState != null) {
        Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
        mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
                ? mLastNonConfigurationInstances.fragments : null);
    }
    mFragments.dispatchCreate();
    getApplication().dispatchActivityCreated(this, savedInstanceState);
    if (mVoiceInteractor != null) {
        mVoiceInteractor.attachActivity(this);
    }
    mCalled = true;
}

final void performCreateCommon() {
    mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
            com.android.internal.R.styleable.Window_windowNoDisplay, false);
    mFragments.dispatchActivityCreated();
    mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
}
ここではFragmentの復旧作業を行い、Activityのライフサイクルを記録しやすくするために、Activityの入場を含めて、Transition動画を呼び出しました。しかし、私たちはActivity葃onCreateにおいても、レイアウトをロードするためにset ContentViewを呼び出す方法があります。そうでないとActivityはPhone Windowだけでは何もできません。この方法を持って一緒に分析しなければなりません。set ContentViewは上記のonCreateの実行後に呼び出します。コードは以下の通りです。
public void setContentView(@LayoutRes int layoutResID) {
    //    getWindow  PhoneWindow
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}
私たちが設定したレイアウトは、Phone Windowにロードされています。関連コードは以下の通りです。
//fram eworks/base/core/java/com/android/internal/policy/Phone Window.java
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.
    // mContentParent      layout    
    if (mContentParent == null) {
        //    Decor
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }

    if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        ...
    } else {
        mLayoutInflater.inflate(layoutResID, mContentParent);
    }
    ...
}
まず、Decorがどのように初期化されたかを見てください。
private void installDecor() {
    mForceDecorInstall = false;
    if (mDecor == null) {
        mDecor = generateDecor(-1);
        ...
    } else {
        mDecor.setWindow(this);
    }
    if (mContentParent == null) {
        mContentParent = generateLayout(mDecor);

        ...
    }
}

protected DecorView generateDecor(int featureId) {
    // System process doesn't have application context and in that case we need to directly use
    // the context we have. Otherwise we want the application context, so we don't cling to the
    // activity.
    Context context;
    if (mUseDecorContext) {
        Context applicationContext = getContext().getApplicationContext();
        if (applicationContext == null) {
            context = getContext();
        } else {
            context = new DecorContext(applicationContext, getContext().getResources());
            if (mTheme != -1) {
                context.setTheme(mTheme);
            }
        }
    } else {
        context = getContext();
    }
    return new DecorView(context, featureId, this, getAttributes());
}

protected ViewGroup generateLayout(DecorView decor) {
    ...
    // android.R.id.content
    ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
    
    int layoutResource;
    ...

    mDecor.startChanging();
    //      Feature         
    mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
    ...
    return contentParent;
}
これでDecorViewが作成され、いくつかの初期化が完了しました。次にPhone Window方法に戻ります。ここでmLayoutInflate.inflate(layoutReson,mContront Part)方法でmContront Partに追加しました。関連コードは以下の通りです。
/fram eworks/base/core/java/android/view/Layout Inflater.java
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
    return inflate(resource, root, root != null);
}

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
    final Resources res = getContext().getResources();
    ...

    final XmlResourceParser parser = res.getLayout(resource);
    try {
        return inflate(parser, root, attachToRoot);
    } finally {
        parser.close();
    }
}
XMLを解析する過程は注目しなくなります。
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
    synchronized (mConstructorArgs) {
        ...

        try {
            // Look for the root node.
            int type;
            while ((type = parser.next()) != XmlPullParser.START_TAG &&
                    type != XmlPullParser.END_DOCUMENT) {
                // Empty
            }
            ...
            if (TAG_MERGE.equals(name)) {
                ...
                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) {
                    if (DEBUG) {
                        System.out.println("Creating params from root: " +
                                root);
                    }
                    // 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);
                    }
                }

                ...

                // Inflate all children under temp against its context.
                rInflateChildren(parser, temp, attrs, true);

                ...

                // 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) {
            ...
        }

        return result;
    }
}
ここで二つの関数を見ました。rInflateとrInflate Children、この二つの関数を組み合わせてみます。コードは以下の通りです。
final void rInflateChildren(XmlPullParser parser, View parent, AttributeSet attrs,
        boolean finishInflate) throws XmlPullParserException, IOException {
    rInflate(parser, parent, parent.getContext(), attrs, finishInflate);
}

void rInflate(XmlPullParser parser, View parent, Context context,
        AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {

    final int depth = parser.getDepth();
    int type;

    while (((type = parser.next()) != XmlPullParser.END_TAG ||
            parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {

        if (type != XmlPullParser.START_TAG) {
            continue;
        }

        final String name = parser.getName();
        
        if (TAG_REQUEST_FOCUS.equals(name)) {
            parseRequestFocus(parser, parent);
        } else if (TAG_TAG.equals(name)) {
            parseViewTag(parser, parent, attrs);
        } else if (TAG_INCLUDE.equals(name)) {
            if (parser.getDepth() == 0) {
                throw new InflateException(" cannot be the root element");
            }
            parseInclude(parser, context, parent, attrs);
        } else if (TAG_MERGE.equals(name)) {
            throw new InflateException(" must be the root element");
        } else {
            final View view = createViewFromTag(parent, name, context, attrs);
            final ViewGroup viewGroup = (ViewGroup) parent;
            final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
            rInflateChildren(parser, view, attrs, true);
            viewGroup.addView(view, params);
        }
    }

    if (finishInflate) {
        parent.onFinishInflate();
    }
}
これらの2つの関数は、すべてのViewが解析済みになるまで循環的に呼び出し、最終的にはparent.onFinish Inflate()メソッドに呼び出し、inflateプロセスを完了することができます。
以上の手順を経て、Activityは作成されました。同時にDecorViewと私達のレイアウトファイルは初期化されましたが、DecorViewはまだWindowに追加されていませんので、表示できません。私たちは再びActivityThread((zhi performLaunchActivity)に戻ります。次はactivity.performStart()です。コードは以下の通りです。
/fram eworks/base/core/java/android/ap/Activity.java
final void performStart() {
    mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
    mFragments.noteStateNotSaved();
    mCalled = false;
    mFragments.execPendingActions();
    mInstrumentation.callActivityOnStart(this);
    if (!mCalled) {
        throw new SuperNotCalledException(
            "Activity " + mComponent.toShortString() +
            " did not call through to super.onStart()");
    }
    mFragments.dispatchStart();
    mFragments.reportLoaderStart();
    ...
}
ここではFragmentとActivityライフサイクルの問題を見ました。後でまた研究しに来ます。InstructivityOnStartとActivityは何もしていません。ここでコードを貼り付けます。
// /frameworks/base/core/java/android/app/Instrumentation.java
public void callActivityOnStart(Activity activity) {
    activity.onStart();
}

// /frameworks/base/core/java/android/app/Activity.java
protected void onStart() {
    if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStart " + this);
    mCalled = true;

    mFragments.doLoaderStart();

    getApplication().dispatchActivityStarted(this);
}
引き続きActivityThread((Cn performLaunchActivity)に戻ります。次にActivityThread((zhi)handleResum Activityメソッドを呼び出しました。コードは以下の通りです。
/fram eworks/base/core/java/android/ap/ActivityThread.java
final void handleResumeActivity(IBinder token,
        boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
    ...

    // TODO Push resumeArgs into the activity for consideration
    r = performResumeActivity(token, clearHide, reason);

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

        ...

        // 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 (r.window == null && !a.mFinished && willBeVisible) {
            r.window = r.activity.getWindow();
            View decor = r.window.getDecorView();
            //   Decor   
            decor.setVisibility(View.INVISIBLE);
            ...
            // Window    ,          
            if (r.mPreserveWindow) {
                a.mWindowAdded = true;
                r.mPreserveWindow = false;
                ...
            }
            if (a.mVisibleFromClient && !a.mWindowAdded) {
                a.mWindowAdded = true;
                //  Decor   Window 
                wm.addView(decor, 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) {
            ...
        }

        // 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) {
            ...
            r.activity.mVisibleFromServer = true;
            mNumVisibleActivities++;
            if (r.activity.mVisibleFromClient) {
                //      
                r.activity.makeVisible();
            }
        }

        ...

        // Tell the activity manager we have resumed.
        if (reallyResume) {
            try {
                ActivityManagerNative.getDefault().activityResumed(token);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }

    } else {
        ...
    }
}
ここでは多くの仕事を処理しています。まずperformResume Activityを通じてActivity胫onResumeを呼び出して、ActivityをonResume状態にしてからDecorviewをWindowに追加して表示します。まずperformResume Activityの実現を見ます。
public final ActivityClientRecord performResumeActivity(IBinder token,
        boolean clearHide, String reason) {
    ActivityClientRecord r = mActivities.get(token);
    if (localLOGV) Slog.v(TAG, "Performing resume of " + r
            + " finished=" + r.activity.mFinished);
    if (r != null && !r.activity.mFinished) {
        if (clearHide) {
            r.hideForNow = false;
            r.activity.mStartedActivity = false;
        }
        try {
            ...
            r.activity.performResume();

            ...
        } catch (Exception e) {
            ...
        }
    }
    return r;
}
引き続き追跡して、Activity〓〓performResum方法に着きました。コードは以下の通りです。
final void performResume() {
    performRestart();

    ...
    // mResumed is set by the instrumentation
    mInstrumentation.callActivityOnResume(this);
    ...

    // Now really resume, and install the current status bar and menu.
    mCalled = false;

    mFragments.dispatchResume();
    mFragments.execPendingActions();

    onPostResume();
    ...
}

final void performRestart() {
    ...
    // Activity Stop         
    if (mStopped) {
        mStopped = false;

        ...

        mCalled = false;
        mInstrumentation.callActivityOnRestart(this);
        if (!mCalled) {
            throw new SuperNotCalledException(
                "Activity " + mComponent.toShortString() +
                " did not call through to super.onRestart()");
        }
        // onRestart      onStart
        performStart();
    }
}
その後、InstruumentationでActivityOResumeを呼び出してActivityメソッドを呼び出し、その後ActivityはonResume状態に入りました。最後にActivityがResumeを確認した後、ActivityManagerServiceに他の操作を行うように通知しました。
次に、WindowでDecorViewをロードする過程を見ます。Windowに設定されたWindowManagerによって完成されたのです。つまりWindowManager Implのオブジェクトです。関連コードは以下の通りです。
/frame eworks/base/core/java/android/view/WindowManagerImpl.java
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyDefaultToken(params);
    mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}

private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
DecorViewがグローバルWindowManagerGlobalに追加されているのが見えます。関連コードは以下の通りです。
/frame eworks/base/core/java/android/view/WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
    ...
    synchronized (mLock) {
        ...

        root = new ViewRootImpl(view.getContext(), display);

        view.setLayoutParams(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(view, wparams, panelParentView);
    } catch (RuntimeException e) {
        ...
    }
}
WindowManagerGlobalには一連のView RootImplが保存されています。レイアウトを追加するごとに、View RootImplオブジェクトを新規作成します。次はそのsetView方法を見ます。コードは以下の通りです。
/fram eworks/base/core/java/android/view/View RootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    synchronized (this) {
        // if       View
        if (mView == null) {
            mView = view;

            ...

            // Schedule the first layout -before- adding to the window
            // manager, to make sure we do the relayout before receiving
            // any other events from the system.
            requestLayout();
            ...
            try {
                ...
                res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                        getHostVisibility(), mDisplay.getDisplayId(),
                        mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                        mAttachInfo.mOutsets, mInputChannel);
            } catch (RemoteException e) {
                ...
            }

            ...

            view.assignParent(this);
            ...
        }
    }
}
ここではまずrequest Layoutメソッドを呼び出してページをレンダリングし、mWindowSession.addToDisplayを通じてWindowManager Serviceにページを追加します。まず前の方法を見ます。コードは以下の通りです。
@Override
public void requestLayout() {
    if (!mHandlingLayoutInLayoutRequest) {
        checkThread();
        mLayoutRequested = true;
        scheduleTraversals();
    }
}
ここでcheckThreadを見て思わず目の前が明るくなりました。その実現は以下の通りです。
void checkThread() {
    if (mThread != Thread.currentThread()) {
        throw new CalledFromWrongThreadException(
                "Only the original thread that created a view hierarchy can touch its views.");
    }
}
つまり、OResumeの後、Activityは非UIスレッドでUIを更新するかどうかを確認することができる。他の部分を見続けてください。コードは以下の通りです。
void scheduleTraversals() {
    if (!mTraversalScheduled) {
        mTraversalScheduled = true;
        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
        mChoreographer.postCallback(
                Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
        if (!mUnbufferedInputDispatch) {
            scheduleConsumeBatchedInput();
        }
        notifyRendererOfFramePending();
        pokeDrawLockIfNeeded();
    }
}
ここではMessage Queueメソッドを使用して、同期障壁と呼ばれるこの方法で、非同期メッセージを送ることができます。このメッセージは優先的に実行されます。具体的な説明は私の文章を見ることができます。Androidソース分析のHandler。次のコードの一部はNativeに進みます。最終的にはmTraversalRunnableというフィードバックになります。コードは以下の通りです。
final class TraversalRunnable implements Runnable {
    @Override
    public void run() {
        doTraversal();
    }
}
つまりシステムはTraversalRunnable方法を早く実行します。コードは以下の通りです。
void doTraversal() {
    if (mTraversalScheduled) {
        mTraversalScheduled = false;
        mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
        ...
        performTraversals();
        ...
    }
}
まず障壁を解除し、performTraversals方法を実行します。ここからViewはmeasre、layout、drawなどのプロセスを行います。紙面に限り、次の文章は分析を続けます。
下一篇:Androidソース分析のアプリ起動プロセス(二)
次の編:Androidソース分析のActivity起動とView作成プロセス(二)