Activity的绘制流程简单分析(基于android 4.0源码进行分析)

要明白这个流程,我们还得从第一部开始,大家都知道 在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

 *

 *      http://www.apache.org/licenses/LICENSE-2.0

 *

 * 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

 *

 *      http://www.apache.org/licenses/LICENSE-2.0

 *

 * 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

**

**     http://www.apache.org/licenses/LICENSE-2.0

**

** 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的绘制流程~

时间: 2024-10-09 19:50:53

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

Android自定义view教程06--Activity的绘制流程简单分析(基于android 4.0源码进行分析)

要明白这个流程,我们还得从第一部开始,大家都知道 在activity里面 setcontentview 调用结束以后 就可以看到程序加载好我们的布局文件了,从而让我们在手机上看到这个画面. 那么我们来看一下这个源码是如何实现的. 1 /** 2 * Set the activity content from a layout resource. The resource will be 3 * inflated, adding all top-level views to the activit

[Android编译(二)] 从谷歌官网下载android 6.0源码、编译并刷入nexus 6p手机

1 前言 经过一周的奋战,终于从谷歌官网上下载最新的android 6.0.1_r62源码,编译成功,并成功的刷入nexus6p,接着root完毕,现写下这篇博客记录一下实践过程. 2 简介 自己下载android系统源码,修改定制,然后编译刷入安卓手机,想想还有点小激动呢.简单点说一句话--定制我们自己的MIUI,这就是android的魅力,这篇博客博主就来教大家实现自己的定制系统. 首先,要明白下面的基础知识: (1) 什么是aosp? aosp就是android open source p

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

本文转载自:[Android 编译(一)] Ubuntu 16.04 LTS 成功编译 Android 6.0 源码教程 1 前言 经过3天奋战,终于在Ubuntu 16.04上把Android 6.0的源码编译出来了,各种配置,各种error,各种爬坑,特写此博客记录爬坑经历.先上图,Ubuntu上编译完后成功运行模拟器,如图: 2 编译环境 UbuntuKylin 16.04 LTS Android 6.0_r1 Open JDK 7 3 准备工作 (1) 下载android 6.0源码.

Ubuntu 16.04 LTS 成功编译 Android 6.0 源码教程 (转)

1 前言 经过3天奋战,终于在Ubuntu 16.04上把Android 6.0的源码编译出来了,各种配置,各种error,各种爬坑,特写此博客记录爬坑经历.先上图,Ubuntu上编译完后成功运行模拟器,如图: 2 编译环境 UbuntuKylin 16.04 LTS Android 6.0_r1 Open JDK 7 3 准备工作 (1) 下载Android 6.0源码. Androdi 6.0源码下载地址: http://pan.baidu.com/s/1o6N86a2 感谢下面这位博主上传

EventBus 3.0 源码简要分析

EvenBus 可以在不同模块间传递信息,减少接口的使用. 一.使用例子 <span style="font-size:18px;">public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.la

【android】从源码上分析ListView/GridView调用setEmptyView不起作用的原因及解决办法

当我们使用ListView或GridView的时候,当列表为空的时候,我们往往需要一个Loading或者一段提示文字又或者一个特殊的View来提示用户操作,这个时候就用到了setEmptyView()方法. setEmptyView()其实是AdapterView的方法,而我们开发中常用到的ListView, GridView, ExpandableListView等都是继承于AdapterView的,所以可以直接调用这个方法. 但是问题来了,当你这个emptyview不在当前的View hie

Ubantu16.04进行Android 8.0源码编译

分为4个流程 源码下载 构建编译环境 编译源码 运行 源码下载 安装git并且配置 //安装git sudo apt-get install git //配置git名称和邮箱 git config --global user.name "your name" git config --global user.email "[email protected]" 创建repo的bin目录和源码目录 创建repo的bin目录 midir ~/bin 创建源码目录 midi

下载Android 5.0源码(附源码)

下载方法见我的另一篇博客:http://blog.csdn.net/maosidiaoxian/article/details/41680769 2014-12-24更新:5.0.1源码已上传. 这次下载的是5.0.0_r7的源码,下载到99%的时候遇见以下问题: [plain] view plaincopy Fetching projects:  99% (478/482)  Fetching project platform/external/sqlite error: Cannot fet

Android 5.0源码编译问题

转载: http://blog.csdn.net/shineflowers/article/details/41545057 如果是自己通过repo和git直接从google官网上download的源码,请忽略这个问题,但是由于google在国内被限制登录,通过这一种方法不是每个人都能download下来源码,通常的做法就是从别人那拷贝,然后自己编译,那么通常会出现下面的错误: No rule to make target 'external/chromium_org/third_party/a