Activity的创建和显示以及源码分析记录

Tips:此源码分析基于Android 4.2

先来看看一个Activity上的UI控件结构:

图1-1 Activity中的UI组件结构

好了现在开始分析。。。。。。

一、Activity的创建

了解android的zygote分裂你会知道,每个APP都是zygote的子进程,而他的入口函数是ActivityThread类中的main函数。其中有一个handleLaucherActivity函数,这里就是

创建Activity的地方。

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();

        if (r.profileFd != null) {
            mProfiler.setProfiler(r.profileFile, r.profileFd);
            mProfiler.startProfiling();
            mProfiler.autoStopProfiler = r.autoStopProfiler;
        }
        // Make sure we are running with the most recent config.
        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);
        //重点一
        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            // 重点二
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);

           }

         后面代码省略 ...... 

    }

这里已经标出了两个重点的函数

先来看看第一个performLauncherActivity

这个函数返回一个activity,可见activity确实在这里创建了,先上代码

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

       ......

       Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            //正真创建activity的地方
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

      ......

                if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                //又是一个重点,暂且先不分析,,,
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                //这里回调了Activity的OnCreate
                mInstrumentation.callActivityOnCreate(activity, r.state);
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                if (!r.activity.mFinished) {
                    activity.mCalled = false;
                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    if (!activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPostCreate()");
                    }
                }
            }

      ......

      return activity;
}

这里贴上了关键的代码,由此可见performLauncherActivity函数主要做了两件重要的事情,创建了Activity以及回调了OnCreate。

这里看出他是利用了Java的反射机制根据类名创建了一个Activity

接下来再来看下第二个函数handleResumeActivity,什么都不说先看代码:

          final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
            boolean reallyResume) {
       ......

       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 (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    //关键函数
                    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.
            }
         .......
         }
       

到了这里可以看到多了两个比较重要的对象View, ViewManager, 随后decor对象add到了ViewManager,那么这两个对象到底是什么呢?

getDectorView进去一看原来是Window类的一个抽象方法,那么到底是什么实现了他?

这就要看刚刚哪个Activity的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) {
        attachBaseContext(context);

        mFragments.attachActivity(this, mContainer, null);

        //创建了一个mWindow,这是一个实现了Window抽象方法的对象
        mWindow = PolicyManager.makeNewWindow(this);
        mWindow.setCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);

        ......

        //创建了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;
    }

在handleResumeActivity中的r.window = r.activity.getWindow();我们可以看出这里创建的mWindow给了r.window

public Window getWindow() {
        return mWindow;
    }

由此可见mWindow的getDecorView方法返回的便是我们要认识的哪个View,现在就来看看这个mWindow到底是何方圣神。

创建mWindow时有出现了个PolicyManager,现在先看看这个是什么东西

public final class PolicyManager {
    private static final String POLICY_IMPL_CLASS_NAME =
        "com.android.internal.policy.impl.Policy";

    private static final IPolicy sPolicy;

    static {
        // Pull in the actual implementation of the policy at run-time
        try {
            Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
            sPolicy = (IPolicy)policyClass.newInstance();
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    POLICY_IMPL_CLASS_NAME + " could not be loaded", ex);
        } catch (InstantiationException ex) {
            throw new RuntimeException(
                    POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex);
        } catch (IllegalAccessException ex) {
            throw new RuntimeException(
                    POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex);
        }
    }

    // Cannot instantiate this class
    private PolicyManager() {}

    // The static methods to spawn new policy-specific objects
    public static Window makeNewWindow(Context context) {
        return sPolicy.makeNewWindow(context);
    }

    public static LayoutInflater makeNewLayoutInflater(Context context) {
        return sPolicy.makeNewLayoutInflater(context);
    }

    public static WindowManagerPolicy makeNewWindowManager() {
        return sPolicy.makeNewWindowManager();
    }

    public static FallbackEventHandler makeNewFallbackEventHandler(Context context) {
        return sPolicy.makeNewFallbackEventHandler(context);
    }
}

从这里可以看出调用的PolicyManager.makeNewWindow(this)正真实现是在Policy中

 public Window makeNewWindow(Context context) {
        return new PhoneWindow(context);
    }

至此我们才发现所谓的mWindow其实是一个PhoneWindow对象

现在我们在了看看正真实现getDecorView的PhoneWindow中获得的View到底是什么?

 @Override
    public final View getDecorView() {
        if (mDecor == null) {
            installDecor();
        }
        return mDecor;
    }
private void installDecor() {
        if (mDecor == null) {
            mDecor = generateDecor();
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        }
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);

            // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
            mDecor.makeOptionalFitsSystemWindows();

            mTitleView = (TextView)findViewById(com.android.internal.R.id.title);

         ......
      }

          ......

}

到了这一步我们才发现原来哪个View是一个DecorView,

private final class DecorView extends FrameLayout implements RootViewSurfaceTaker

好了现在解决了我们第一个问题,View到底是什么?现在我们再来分析下ViewManager究竟是什么?

ViewManager wm = a.getWindowManager();

查看activity的getWindowManager以及attach方法我们会发现这正是attach方法中创建的WindowManager

public WindowManager getWindowManager() {
        return mWindowManager;
    }

但是WindowManager只是一个公共的接口,我们还是得进入到attach中的mWindow.setWindowManager()中看看到底发生了什么?

public interface WindowManager extends ViewManager
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {
        mAppToken = appToken;
        mAppName = appName;
        mHardwareAccelerated = hardwareAccelerated
                || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
        if (wm == null) {
            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        }
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
    }
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
        return new WindowManagerImpl(mDisplay, parentWindow);
    }

到此我们终于解决了我们的第二个问题,哪个ViewManager其实是WindowManagerImpl

好了处理了这门多复杂的关系,我们先来总结下:

1、我们是分析到了handleResumeActivity这个函数,想弄清楚View跟ViewManager分别是什么?

2、之后我们返回去查看activity的attache函数,发现其中创建的mWindow跟mWindowManager其实是PhoneWindow与WindowManagerImpl.

3、我们再回到View与ViewManager的创建过程,发下其实View是在PhoneWindow中创建的DecorView而ViewManager正是mWindowManager(即WindowManagerImpl),

在attach中调用Window的setWindowManager时将创建的WindowManagerImpl保存了起来。

经过这般分析再来看这张图:

图1-2 Window与WindowManager

好了,接下来我们继续来分析handleResumeActivity中另一个很关键的函数wm.addView(decor, l);

addView的正真实现实在frameworks\base\core\java\android\view\WindowManagerGlobal.java

public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        if (view == null) {
            throw new IllegalArgumentException("view must not be null");
        }
        if (display == null) {
            throw new IllegalArgumentException("display must not be null");
        }
        if (!(params instanceof WindowManager.LayoutParams)) {
            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
        }

        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
        if (parentWindow != null) {
            parentWindow.adjustLayoutParamsForSubWindow(wparams);
        }

        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 (ViewRootImpl viewRoot : mRoots) {
                                viewRoot.loadSystemProperties();
                            }
                        }
                    }
                };
                SystemProperties.addChangeCallback(mSystemPropertyUpdater);
            }

            int index = findViewLocked(view, false);
            if (index >= 0) {
                throw new IllegalStateException("View " + view
                        + " has already been added to the window manager.");
            }

            // 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 != null ? mViews.length : 0;
                for (int i=0; i<count; i++) {
                    if (mRoots[i].mWindow.asBinder() == wparams.token) {
                        panelParentView = mViews[i];
                    }
                }
            }

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

            view.setLayoutParams(wparams);

            if (mViews == null) {
                index = 1;
                mViews = new View[1];
                mRoots = new ViewRootImpl[1];
                mParams = new WindowManager.LayoutParams[1];
            } else {
                index = mViews.length + 1;
                Object[] old = mViews;
                mViews = new View[index];
                System.arraycopy(old, 0, mViews, 0, index-1);
                old = mRoots;
                mRoots = new ViewRootImpl[index];
                System.arraycopy(old, 0, mRoots, 0, index-1);
                old = mParams;
                mParams = new WindowManager.LayoutParams[index];
                System.arraycopy(old, 0, mParams, 0, index-1);
            }
            index--;

            mViews[index] = view;
            mRoots[index] = root;
            mParams[index] = wparams;
        }

        // do this last because it fires off messages to start doing things
        try {
            root.setView(view, wparams, panelParentView);
        } catch (RuntimeException e) {
            // BadTokenException or InvalidDisplayException, clean up.
            synchronized (mLock) {
                final int index = findViewLocked(view, false);
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
            }
            throw e;
        }
    }

这里有出现了一个新的对象ViewRootImpl以及调用了它的一个重要方法setView,现在我们就来分析下

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks

查看ViewRootImpl的源码可以知道它里面包含了几个重要的成员对象(frameworks\base\core\java\android\view\ViewRootImpl.java)

有一个mSurface,他是Surface类型,而前面提到的UI都是在这上面绘画出来的,可以想象成一个画布

还有一个W类型的内部类,这个类将参与Binder通信

static class W extends IWindow.Stub

并且重写了handleMessage

我们接着看下ViewRootImpl的构造函数:

public ViewRootImpl(Context context, Display display) {
        super();

        if (MEASURE_LATENCY) {
            if (lt == null) {
                lt = new LatencyTimer(100, 1000);
            }
        }

        // Initialize the statics when this class is first instantiated. This is
        // done here instead of in the static block because Zygote does not
        // allow the spawning of threads.
        mWindowSession = WindowManagerGlobal.getWindowSession(context.getMainLooper());
        mDisplay = display;

        CompatibilityInfoHolder cih = display.getCompatibilityInfo();
        mCompatibilityInfo = cih != null ? cih : new CompatibilityInfoHolder();

        mThread = Thread.currentThread();
        mLocation = new WindowLeaked(null);
        mLocation.fillInStackTrace();
        mWidth = -1;
        mHeight = -1;
        mDirty = new Rect();
        mTempRect = new Rect();
        mVisRect = new Rect();
        mWinFrame = new Rect();
        mWindow = new W(this);

        ......

}

这里一个比较重要的函数是getWindowSession

public static IWindowSession getWindowSession(Looper mainLooper) {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
                    IWindowManager windowManager = getWindowManagerService();
                    sWindowSession = windowManager.openSession(
                            imm.getClient(), imm.getInputContext());
                    float animatorScale = windowManager.getAnimationScale(2);
                    ValueAnimator.setDurationScale(animatorScale);
                } catch (RemoteException e) {
                    Log.e(TAG, "Failed to open window session", e);
                }
            }
            return sWindowSession;
        }
    }

这里又是一个Binder机制的跨进程调用,可以看出ViewRootImpl还和WindowManagerServer有着密切的联系,这里就不讨论了。。。。

现在我们来看下setView中的调用的一个重要方法

                public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {

                ......

                // 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();
                if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                    mInputChannel = new InputChannel();
                }
                try {
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
                    collectViewAttributes();
                    // 这里调用了IWindowSession的addToDisplay并且把W类型的mWindow传过去
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mInputChannel);
                } catch (RemoteException e) {
                    mAdded = false;
                    mView = null;
                    mAttachInfo.mRootView = null;
                    mInputChannel = null;
                    mFallbackEventHandler.setView(null);
                    unscheduleTraversals();
                    setAccessibilityFocus(null, null);
                    throw new RuntimeException("Adding window failed", e);
                } finally {
                    if (restore) {
                        attrs.restore();
                    }
                }

               ......

          }
        

现在我们来看看requestLayout函数,这里才是Activity的UI绘制,进去看看发现其实是一个异步任务中执行了那些绘制任务

final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }
void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().removeSyncBarrier(mTraversalBarrier);

            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }

            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "performTraversals");
            try {
                performTraversals();
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
            }

            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }
         //这个函数还是比较麻烦的,这里就给出关键点
         private void performTraversals() {

          ......

          relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);

          ......

           //一些绘制相关工作
          mView.draw(layerCanvas);

           ......
            }
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
            boolean insetsPending) throws RemoteException {

        float appScale = mAttachInfo.mApplicationScale;
        boolean restore = false;
        if (params != null && mTranslator != null) {
            restore = true;
            params.backup();
            mTranslator.translateWindowLayout(params);
        }
        if (params != null) {
            if (DBG) Log.d(TAG, "WindowLayout in layoutWindow:" + params);
        }
        mPendingConfiguration.seq = 0;
        //Log.d(TAG, ">>>>>> CALLING relayout");
        if (params != null && mOrigWindowType != params.type) {
            // For compatibility with old apps, don't crash here.
            if (mTargetSdkVersion < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                Slog.w(TAG, "Window type can not be changed after "
                        + "the window is added; ignoring change of " + mView);
                params.type = mOrigWindowType;
            }
        }
        int relayoutResult = mWindowSession.relayout(
                mWindow, mSeq, params,
                (int) (mView.getMeasuredWidth() * appScale + 0.5f),
                (int) (mView.getMeasuredHeight() * appScale + 0.5f),
                viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
                mWinFrame, mPendingContentInsets, mPendingVisibleInsets,
                mPendingConfiguration, mSurface);
        //Log.d(TAG, "<<<<<< BACK FROM relayout");
        if (restore) {
            params.restore();
        }

        if (mTranslator != null) {
            mTranslator.translateRectInScreenToAppWinFrame(mWinFrame);
            mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets);
            mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets);
        }
        return relayoutResult;
    }

这里是调用了IWindowSession的relayout来获得一个relayoutResult

至此Acitivity的创建和UI的显示就完成了。。。。。。

补充:

既然是Activity的显示,那么必然是少不了显示我们自己设置的UI,一般我们设置的UI都是在OnCreate中的setContentView中设置,现在我们就来看看这个函数到底做了那些事。

Activity中的SetContentView();

public void setContentView(View view) {
        getWindow().setContentView(view);
        initActionBar();
    }

还记得上面所说的Activity显示中有一个Window吧,那个getWindow就是PhoneWindow,那么我们就来看看PhoneWindow中的SetContentView:

@Override
    public void setContentView(View view) {
        setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        mContentParent.addView(view, params);
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
    }

这里的mContentParent是一个ViewGroup类型的,这里我们可以看到它把我们设置的view添加进去了,也就是说绘制ViewGroup是也会把它包含的view绘制出来。

接下来再来看看installDector:

private void installDecor() {
        if (mDecor == null) {
            mDecor = generateDecor();
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        }
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);

            // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
            mDecor.makeOptionalFitsSystemWindows();

            mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
            if (mTitleView != null) {
                mTitleView.setLayoutDirection(mDecor.getLayoutDirection());
                if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
                    View titleContainer = findViewById(com.android.internal.R.id.title_container);
                    if (titleContainer != null) {
                        titleContainer.setVisibility(View.GONE);
                    } else {
                        mTitleView.setVisibility(View.GONE);
                    }
                    if (mContentParent instanceof FrameLayout) {
                        ((FrameLayout)mContentParent).setForeground(null);
                    }
                } else {
                    mTitleView.setText(mTitle);
                }
            } else {
                mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
                if (mActionBar != null) {
                    mActionBar.setWindowCallback(getCallback());
                    if (mActionBar.getTitle() == null) {
                        mActionBar.setWindowTitle(mTitle);
                    }
                    final int localFeatures = getLocalFeatures();
                    if ((localFeatures & (1 << FEATURE_PROGRESS)) != 0) {
                        mActionBar.initProgress();
                    }
                    if ((localFeatures & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
                        mActionBar.initIndeterminateProgress();
                    }

                    boolean splitActionBar = false;
                    final boolean splitWhenNarrow =
                            (mUiOptions & ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW) != 0;
                    if (splitWhenNarrow) {
                        splitActionBar = getContext().getResources().getBoolean(
                                com.android.internal.R.bool.split_action_bar_is_narrow);
                    } else {
                        splitActionBar = getWindowStyle().getBoolean(
                                com.android.internal.R.styleable.Window_windowSplitActionBar, false);
                    }
                    final ActionBarContainer splitView = (ActionBarContainer) findViewById(
                            com.android.internal.R.id.split_action_bar);
                    if (splitView != null) {
                        mActionBar.setSplitView(splitView);
                        mActionBar.setSplitActionBar(splitActionBar);
                        mActionBar.setSplitWhenNarrow(splitWhenNarrow);

                        final ActionBarContextView cab = (ActionBarContextView) findViewById(
                                com.android.internal.R.id.action_context_bar);
                        cab.setSplitView(splitView);
                        cab.setSplitActionBar(splitActionBar);
                        cab.setSplitWhenNarrow(splitWhenNarrow);
                    } else if (splitActionBar) {
                        Log.e(TAG, "Requested split action bar with " +
                                "incompatible window decor! Ignoring request.");
                    }

                    // Post the panel invalidate for later; avoid application onCreateOptionsMenu
                    // being called in the middle of onCreate or similar.
                    mDecor.post(new Runnable() {
                        public void run() {
                            // Invalidate if the panel menu hasn't been created before this.
                            PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
                            if (!isDestroyed() && (st == null || st.menu == null)) {
                                invalidatePanelMenu(FEATURE_ACTION_BAR);
                            }
                        }
                    });
                }
            }
        }
    }

从这里我们可以看出这个函数主要是创建了一个DectorView和ViewGroup(mContentPartent)对象以及创建标题栏或者是ActionBar。

再来看看mContentParent:

protected ViewGroup generateLayout(DecorView decor) {

       ......

       mDecor.startChanging();
        //layoutResource是一个资源ID
        View in = mLayoutInflater.inflate(layoutResource, null);
        decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
        //ID_ANDROID_CONTENT是com.android.internal.R.id.content
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
        if (contentParent == null) {
            throw new RuntimeException("Window couldn't find content container view");
        }

        if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
            ProgressBar progress = getCircularProgressBar(false);
            if (progress != null) {
                progress.setIndeterminate(true);
            }
        }

       ......

        return contentPartent;

}

这里的contentPartent是由findViewById获得,实际是mDectorView的一部分,为什么这么说看看下面的代码就知道了:

 public View findViewById(int id) {
        return getDecorView().findViewById(id);
    }

getDectorView返回的便是mDectorView,到现在我们才算是明白图1-1,其实我们设置的View其实是在DectorView中,而DectorView除了处理我们设置的View还处理了标题栏的显示。。。。。。。。。。。。。。。。。。。

时间: 2024-08-13 23:53:05

Activity的创建和显示以及源码分析记录的相关文章

struts1.2源码分析记录

struts思路:1.struts使用的三板斧ActionForm.DispatchAction.ActionMapping2.主要关注点:Form.Action.Forward3.页面如何发送请求参数,后台如何截取.do请求,如何将参数组装成Form,在Action中如何操作Form,如何查找目标页面,如何将Form返回到页面,页面如何通过标签读取Form属性 框架主流程:Struts所有的请求都要走DispatchAction类的public ActionForward execute(Ac

Android之App界面的挂载与显示及源码分析

前言 入门 视图树 源码分析 前言 好久没有写博客了,都感觉有些生疏了. 总觉的人对自己要求高一些比较好,这样才进步比较快.接下来会继续给大家带来一些更有用的知识. 个人水平有限,如果感觉我的博客对您有用处,那就留个言给下鼓励:如果那里写的有误,请各位看客老爷多多拍砖! 注意:此处我使用的IDE是Android Studio 入门 相信每个人在学习Android时,都创建过很多Demo工程,那么下面的代码,大家一定非常眼熟了. public class MainActivity extends

seajs3.0.0源码分析记录

自己边读变加了一些注释,理解了一下seajs3.0.0工作的流程.正则没有一个个去理解,插件模块也没看, 以后有时间了可以补充完整~ 事件系统中事件队列的获取&定义方法 var list = events[name] || (events[name] = []) 以前自己写都是 if(!events[name]){ events[name]=[]; } var list=events[name]; 囧 加载模块文件的方法 webworker环境下加载模块文件 获取seajs的加载路径: var

Hadoop-2.4.1学习之创建fsimage和edits源码分析

在Hadoop中fsimage保存最新的检查点信息,edits保存自最新检查点后的命名空间的变化.在分析hdfs namenode–format的源代码时,已经明确了该过程根据配置文件的信息创建fsimage和edits文件,这篇文章具体分析一下创建fsimage和edits文件的源代码.在NameNode的format方法中,有如下的代码: FSImage fsImage = new FSImage(conf, nameDirsToFormat, editDirsToFormat); try

建筑材料asp.net mvc项目源码分析记录

1.开发工具 vs2010 sp1 mvc4, 问题: 最近遇到项目开发项目,需要缺少的 Web 组件才能进行加载.是否立即使用 Web 平台安装程序下载并安装这些组件? 解决方法如下: 1. 用记事本打开项目XXX.csproj文件,找到WebProjectProperties节点下的 <UseIIS>True</UseIIS>节点,然后改为     <UseIIS>false</UseIIS>即可:

Docker源码分析(五):Docker Server的创建

1.Docker Server简介 Docker架构中,Docker Server是Docker Daemon的重要组成部分.Docker Server最主要的功能是:接受用户通过Docker Client发送的请求,并按照相应的路由规则实现路由分发. 同时,Docker Server具备十分优秀的用户友好性,多种通信协议的支持大大降低Docker用户使用Docker的门槛.除此之外,Docker Server设计实现了详尽清晰的API接口,以供Docker用户选择使用.通信安全方面,Docke

DialogFragment源码分析

目录介绍 1.最简单的使用方法 1.1 官方建议 1.2 最简单的使用方法 1.3 DialogFragment做屏幕适配 2.源码分析 2.1 DialogFragment继承Fragment 2.2 onCreate(@Nullable Bundle savedInstanceState)源码分析 2.3 setStyle(@DialogStyle int style, @StyleRes int theme) 2.4 onActivityCreated(Bundle savedInstan

Dialog源码分析

目录介绍 1.简单用法 2.AlertDialog源码分析 2.1 AlertDialog.Builder的构造方法 2.2 通过AlertDialog.Builder对象设置属性 2.3 builder.create方法 2.4 看看create方法中的P.apply(dialog.mAlert)源码 2.5 看看AlertDialog的show方法 3.Dialog源码分析 3.1 Dialog的构造方法 3.2 Dialog生命周期 3.3 Dialog中show方法展示弹窗 3.4 Di

PopupWindow源码分析

目录介绍 1.最简单的创建方法 1.1 PopupWindow构造方法 1.2 显示PopupWindow 1.3 最简单的创建 1.4 注意问题宽和高属性 2.源码分析 2.1 setContentView(View contentView) 2.2 showAsDropDown()源码 2.3 dismiss()源码分析 2.4 PopupDecorView源码分析 3.经典总结 3.1 PopupWindow和Dialog有什么区别? 3.2 创建和销毁的大概流程 3.3 为何弹窗点击一下