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

来源:互联网 发布:thinkpad推荐 知乎 编辑:程序博客网 时间:2024/06/05 14:48

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还处理了标题栏的显示。。。。。。。。。。。。。。。。。。。









1 0