要明白这个流程,我们还得从第一部开始,大家都知道 在activity里面 setcontentview 调用结束以后 就可以看到程序加载好我们的布局文件了,从而让我们在手机上看到这个画面。

那么我们来看一下这个源码是如何实现的。

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
/**
     * Set the activity content from a layout resource.  The resource will be
     * inflated, adding all top-level views to the activity.
     *
     * @param layoutResID Resource ID to be inflated.
     *
     * [url=home.php?mod=space&uid=189949]@See[/url] #setContentView(android.view.View)
     * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
     */
    public void setContentView(int layoutResID) {
        getWindow().setContentView(layoutResID);
        initActionBar();
    }

我们这里看到是调用了getwindow的返回值 来调用setcontentview 方法的。

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
/**     * Retrieve the current {@link android.view.Window} for the activity.
     * This can be used to directly access parts of the Window API that
     * are not available through Activity/Screen.
     *
     * [url=home.php?mod=space&uid=309376]@return[/url] Window The current window, or null if the activity is not
     *         visual.
     */
    public Window getWindow() {
        return mWindow;
    }

我们再来看看mWindow 这个值是从哪来的。

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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);
         
        mWindow = PolicyManager.makeNewWindow(this);
        mWindow.setCallback(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;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
 
        mWindow.setWindowManager(null, mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;
    }

注意看11行的代码 我们发现这个mWindow的值 是通过 makeNewWindow这个方法来实现的。我们再来看看这个方法,当然了我们要先找到这个类,这个类位于

<ignore_js_op>

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/* * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
package com.android.internal.policy;
 
import android.content.Context;
import android.view.FallbackEventHandler;
import android.view.LayoutInflater;
import android.view.Window;
import android.view.WindowManagerPolicy;
 
import com.android.internal.policy.IPolicy;
 
/**
 * {@hide}
 */
 
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);
    }
}

这里发现是一个反射的动态加载,我们暂时不去深究他,继续看代码,找到Policy这个类,他位于<ignore_js_op>

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/* * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
package com.android.internal.policy.impl;
 
import android.content.Context;
import android.util.Log;
import android.view.FallbackEventHandler;
import android.view.LayoutInflater;
import android.view.Window;
import android.view.WindowManagerPolicy;
 
import com.android.internal.policy.IPolicy;
import com.android.internal.policy.impl.PhoneLayoutInflater;
import com.android.internal.policy.impl.PhoneWindow;
import com.android.internal.policy.impl.PhoneWindowManager;
 
/**
 * {@hide}
 */
 
// Simple implementation of the policy interface that spawns the right
// set of objects
public class Policy implements IPolicy {
    private static final String TAG = "PhonePolicy";
 
    private static final String[] preload_classes = {
        "com.android.internal.policy.impl.PhoneLayoutInflater",
        "com.android.internal.policy.impl.PhoneWindow",
        "com.android.internal.policy.impl.PhoneWindow$1",
        "com.android.internal.policy.impl.PhoneWindow$ContextMenuCallback",
        "com.android.internal.policy.impl.PhoneWindow$DecorView",
        "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState",
        "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState",
    };
 
    static {
        // For performance reasons, preload some policy specific classes when
        // the policy gets loaded.
        for (String s : preload_classes) {
            try {
                Class.forName(s);
            } catch (ClassNotFoundException ex) {
                Log.e(TAG, "Could not preload class for phone policy: " + s);
            }
        }
    }
 
    public Window makeNewWindow(Context context) {
        return new PhoneWindow(context);
    }
 
    public LayoutInflater makeNewLayoutInflater(Context context) {
        return new PhoneLayoutInflater(context);
    }
 
    public WindowManagerPolicy makeNewWindowManager() {
        return new PhoneWindowManager();
    }
 
    public FallbackEventHandler makeNewFallbackEventHandler(Context context) {
        return new PhoneFallbackEventHandler(context);
    }
}

看62行代码,到这里我们就发现了 在activity里 getwindow 返回的 实际上就是这个phonewindow对象!!!!!!!!!!!!!!我们继续看这个phonewindow类 他位于<ignore_js_op>注意在这里我就不放这个类的源码了,因为2000多行。。。我只抽部分重要的说一下

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
 * Android-specific Window.
 * <p>
 * todo: need to pull the generic functionality out into a base class
 * in android.widget.
 */
public class PhoneWindow extends Window implements MenuBuilder.Callback {
 
    private final static String TAG = "PhoneWindow";
 
    private final static boolean SWEEP_OPEN_MENU = false;
 
    /**
     * Simple callback used by the context menu and its submenus. The options
     * menu submenus do not use this (their behavior is more complex).
     */
    final DialogMenuCallback mContextMenuCallback = new DialogMenuCallback(FEATURE_CONTEXT_MENU);
 
    final TypedValue mMinWidthMajor = new TypedValue();
    final TypedValue mMinWidthMinor = new TypedValue();
 
    // This is the top-level view of the window, containing the window decor.
    private DecorView mDecor;
 
    // 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.
    private ViewGroup mContentParent;
 
    SurfaceHolder.Callback2 mTakeSurfaceCallback;
     
    InputQueue.Callback mTakeInputQueueCallback;
     
    private boolean mIsFloating;
 
    private LayoutInflater mLayoutInflater;
 
    private TextView mTitleView;
     
    private ActionBarView mActionBar;
    private ActionMenuPresenterCallback mActionMenuPresenterCallback;
    private PanelMenuPresenterCallback mPanelMenuPresenterCallback;
 
    private DrawableFeatureState[] mDrawables;
 
    private PanelFeatureState[] mPanels;

看22和23行代码 我们就知道 这个DectorView 就是我们绘制view的时候 最顶层的那个view。换句话说就是最根部的视图。

而且 再继续跟代码 我们会发现 他就是phonewindow的一个内部类 注意看他是继承的framelayout

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
       /* package */int mDefaultOpacity = PixelFormat.OPAQUE;
 
       /** The feature ID of the panel, or -1 if this is the application's DecorView */
       private final int mFeatureId;
 
       private final Rect mDrawingBounds = new Rect();
 
       private final Rect mBackgroundPadding = new Rect();
 
       private final Rect mFramePadding = new Rect();
 
       private final Rect mFrameOffsets = new Rect();
 
       private boolean mChanging;
 
       private Drawable mMenuBackground;
       private boolean mWatchingForMenu;
       private int mDownY;
 
       private ActionMode mActionMode;
       private ActionBarContextView mActionModeView;
       private PopupWindow mActionModePopup;
       private Runnable mShowActionModePopup;
 
       public DecorView(Context context, int featureId) {
           super(context);
           mFeatureId = featureId;
       }

所以到这里我们可以发现 在activity里调用setconteview的时候 最终就是调用的phonewindow的这个方法

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
@Overridepublic void setContentView(int layoutResID) {
  if (mContentParent == null) {
    installDecor();
  } else {
    mContentParent.removeAllViews();
  }
  mLayoutInflater.inflate(layoutResID, mContentParent);
  final Callback cb = getCallback();
  if (cb != null && !isDestroyed()) {
    cb.onContentChanged();
  }
}

这里代码其实也很好理解,如果是第一次调用就installDecor 否则就remove所有的view 我们来看这个installdector的代码

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
private void installDecor() {        if (mDecor == null) {
            mDecor = generateDecor();
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
        }
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);
 
            mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
            if (mTitleView != null) {
                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);
                            }
                        }
                    });
                }
            }
        }
    }

注意看第八行代码 这个就是绘制activity根布局最关键的地方  这个函数一共有300行左右 我也不能全部放上来,有兴趣的同学可以自己看一下源码,我在这截取部分重要的说。

其实重要的代码就是这么一些

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
int layoutResource;
        int features = getLocalFeatures();
        // System.out.println("Features: 0x" + Integer.toHexString(features));
        if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
            if (mIsFloating) {
                TypedValue res = new TypedValue();
                getContext().getTheme().resolveAttribute(
                        com.android.internal.R.attr.dialogTitleIconsDecorLayout, res, true);
                layoutResource = res.resourceId;
            } else {
                layoutResource = com.android.internal.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 = com.android.internal.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(
                        com.android.internal.R.attr.dialogCustomTitleDecorLayout, res, true);
                layoutResource = res.resourceId;
            } else {
                layoutResource = com.android.internal.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(
                        com.android.internal.R.attr.dialogTitleDecorLayout, res, true);
                layoutResource = res.resourceId;
            } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
                if ((features & (1 << FEATURE_ACTION_BAR_OVERLAY)) != 0) {
                    layoutResource = com.android.internal.R.layout.screen_action_bar_overlay;
                } else {
                    layoutResource = com.android.internal.R.layout.screen_action_bar;
                }
            } else {
                layoutResource = com.android.internal.R.layout.screen_title;
            }
            // System.out.println("Title!");
        } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
            layoutResource = com.android.internal.R.layout.screen_simple_overlay_action_mode;
        } else {
            // Embedded, so no decoration is needed.
            layoutResource = com.android.internal.R.layout.screen_simple;
            // System.out.println("Simple!");
        }
 
        mDecor.startChanging();
 
        View in = mLayoutInflater.inflate(layoutResource, null);
        decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));

这个layoutResource的值 实际上就代表了窗口修饰的哪些布局文件,你看最后两行代码就知道

当我们确定了这个布局文件以后就把她add 到decor这个对象里。

所以我们就能想明白 为啥 我们的requestWindowFeature这个方法一定要在setContentview前面调用才有作用了~~

然后给大家随便看下布局文件吧,就是系统自带的这些跟布局。

<ignore_js_op>

这种大家肯定经常用了,就是上面有个标题 然后下面就放我们自己的布局文件来展示内容

当然了还有人喜欢用全屏的screen_simple,他的代码也是很简单的。这里不截图上代码

[XML] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?xml version="1.0" encoding="utf-8"?><!--
/* //device/apps/common/assets/res/layout/screen_simple.xml
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
 
This is an optimized layout for a screen, with the minimum set of features
enabled.
-->
 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:fitsSystemWindows="true"
    android:orientation="vertical">
    <ViewStub android:id="@+id/action_mode_bar_stub"
              android:inflatedId="@+id/action_mode_bar"
              android:layout="@layout/action_mode_bar"
              android:layout_width="match_parent"
              android:layout_height="wrap_content" />
    <FrameLayout
         android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:foregroundInsidePadding="false"
         android:foregroundGravity="fill_horizontal|top"
         android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>

那 注意 33行代码  android:id="@android:id/content" 这个地方跟我们上一张的博客 那边有一样的地方,都是用的这个id content为根布局的,有兴趣的同学可以看看我们view教程05的结尾部分,

两个串起来看就能明白了~~~

然后看一下这个函数 另外一个重要的代码

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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);
            }
        }
 
        // Remaining setup -- of background and title -- that only applies
        // to top-level windows.
        if (getContainer() == null) {
            Drawable drawable = mBackgroundDrawable;
            if (mBackgroundResource != 0) {
                drawable = getContext().getResources().getDrawable(mBackgroundResource);
            }
            mDecor.setWindowBackground(drawable);
            drawable = null;
            if (mFrameResource != 0) {
                drawable = getContext().getResources().getDrawable(mFrameResource);
            }
            mDecor.setWindowFrame(drawable);
 
            // System.out.println("Text=" + Integer.toHexString(mTextColor) +
            // " Sel=" + Integer.toHexString(mTextSelectedColor) +
            // " Title=" + Integer.toHexString(mTitleColor));
 
            if (mTitleColor == 0) {
                mTitleColor = mTextColor;
            }
 
            if (mTitle != null) {
                setTitle(mTitle);
            }
            setTitleColor(mTitleColor);
        }
 
        mDecor.finishChanging();
 
        return contentParent;

返回值是contentParent 而他的值实际上就是我们那个布局文件里装内容的android id content,很好理解吧

所以generateLayout这个函数的作用就是 确定一下我们activity的显示风格还有把content这个framelayout的值

给mContentParent,然后通过第8行的代码就把我们的布局文件添加到这个freamlayout里了。

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
@Override
   public void setContentView(int layoutResID) {
       if (mContentParent == null) {
           installDecor();
       } else {
           mContentParent.removeAllViews();
       }
       mLayoutInflater.inflate(layoutResID, mContentParent);
       final Callback cb = getCallback();
       if (cb != null && !isDestroyed()) {
           cb.onContentChanged();
       }
   }

最终由ActivityManagerService 这个类还显示我们的decorview。

最后我们再把前面的流程简单复述一下

启动一个activity的时候,我们最终是调用的phonewindow的setcontent方法 ,这个方法会创建一个decorview对象

然后再过一遍窗口属性这个流程,最后取得android id content 这个framelayout,然后将布局文件添加到这个framelayout里面

最后由activitymanagerservice负责把这个最终的界面展示出来~~~

自定义view 07 将会讲一下view的绘制流程~

Activity的绘制流程简单分析(基于android 4.0源码进行分析)的更多相关文章

  1. 从谷歌官网下载android 6.0源码、编译并刷入nexus 6p手机

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/fuchaosz/article/details/52473660 1 前言 经过一周的奋战,终于从谷 ...

  2. [Android 编译(一)] Ubuntu 16.04 LTS 成功编译 Android 6.0 源码教程

    本文转载自:[Android 编译(一)] Ubuntu 16.04 LTS 成功编译 Android 6.0 源码教程 1 前言 经过3天奋战,终于在Ubuntu 16.04上把Android 6. ...

  3. Ubantu16.04进行Android 8.0源码编译

    参考这篇博客 经过测试,8.0源码下载及编译之后,占用100多G的硬盘空间,尽量给ubantu系统多留一些硬盘空间,如果后续需要在编译好的源码上进行开发,需要预留更多的控件,为了防止后续出现文件权限问 ...

  4. Android Xlistview的源码浅度分析 监听ListView上下滑动 以及是否到顶和底部

    如转载 请注明出处 http://blog.csdn.net/sk719887916 比如我们很多项目中会用到listview 并且要对listview滑动方向进行判断 也有需要的到listview是 ...

  5. Android 4.0源码目录结构

    转:http://blog.csdn.net/xiangjai/article/details/9012387 在学习Android的过程中,学习写应用还好,一开始不用管太多代码,直接调用函数就可以了 ...

  6. Android 4.0源码结构

    Android 4.0 |-- Makefile |-- bionic (bionic C库) |-- bootable (启动引导相关代码) |-- build (存放系统编译规则及generic等 ...

  7. Android 5.0源码编译问题

    如果是自己通过repo和git直接从google官网上download的源码,请忽略这个问题,但是由于google在国内被限制登录,通过这一种方法不是每个人都能download下来源码,通常的做法就是 ...

  8. 下载Android 5.0源码(附源码)

    下载方法见我的另一篇博客:http://blog.csdn.net/maosidiaoxian/article/details/41680769 2014-12-24更新:5.0.1源码已上传. 这次 ...

  9. Backbone.js 1.0.0源码架构分析(二)——Event

    (function(){ //省略前面代码 var Events = Backbone.Events = { // 根据name订阅事件,push到this._events[name] on: fun ...

随机推荐

  1. BZOJ 1194: [HNOI2006]潘多拉的盒子( BFS + tarjan + dp )

    O(S²)枚举2个诅咒机, 然后O(n²)BFS去判断. 构成一个有向图, tarjan缩点, 然后就是求DAG的最长路.. ------------------------------------- ...

  2. BZOJ 1618: [Usaco2008 Nov]Buying Hay 购买干草( dp )

    无限背包dp.. 因为题目中说至少到 H 磅 , 我就直接把 H * 2 了.. ----------------------------------------------------------- ...

  3. chown命令详解

    chown将指定文件的拥有者改为指定的用户或组,用户可以是用户名或者用户ID:组可以是组名或者组ID:文件是以空格分开的要改变权限的文件列表,支持通配符.系统管理员经常使用chown命令,在将文件拷贝 ...

  4. 大神的vim配置

    大神的vim配置,O(∩_∩)O spf13-vim : Steve Francia's Vim Distribution __ _ _____ _ ___ _ __ / _/ |___ / __ _ ...

  5. Linux下Tomcat catalina.out自动归档,以及logrotate 配置详解

    Linux下Tomcat catalina.out自动归档 如果 catalina.out 日志达到 2GB 大小的时候,Tomcat 因为缓存问题,便没有办法继续输出日志了.  为了避免这种情况,你 ...

  6. python 字典有序无序及查找效率,hash表

    刚学python的时候认为字典是无序,通过多次插入,如di = {}, 多次di['testkey']='testvalue' 这样测试来证明无序的.后来接触到了字典查找效率这个东西,查了一下,原来字 ...

  7. 转:C++中引用传递与指针传递区别

    从概念上讲.指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变. 而引用是一个别名,它在逻辑上不是独立的,它的存在具有 ...

  8. (step6.3.5)hdu 1281(棋盘游戏——二分图的完美匹配)

    题目大意:本体是中文题.读者可以直接在OJ上看 解题思路: 1)完美匹配:所有的端点都是匹配点 2)对于二分图的完美匹配,我们需要用一个数组来存储匹配点.(而二分图的其他问题(我们则可以直接使用变量来 ...

  9. oracle rowid 详解

    oracle rowid详解 今天是2013-09-15,存储在数据库中的每一行数据都有一个地址,oracle使用rowid数据类型在存储地址.rowid有如下类别: 1)physical rowid ...

  10. Linux下的定时器

    以下摘自linux下的man文件:(man  getitimer) #include  <sys/time.h> int  getitimer(int which,  struct iti ...