setContentView()源码的理解

原创 2016年05月30日 21:05:47

setContentView()源码的理解

通俗的解释

使用场景

在Activity中的onCreate()方法中,我们会使用setContentView()给Activity加载布局。但实际情况却不是我们通常使用时理解的那样。正如setContentView()方法名那样,是将layout设置给content,而不是设置给Activity。

先放结论

Activity的布局是有特定的模板,我们通常只是给Content区域填充View
以screen_custom_title.xml模板为例(查看源码请按这里),会得到下图

这里写图片描述
简单梳理一下执行流程:

Created with Raphaël 2.1.0setContentView(layout)初始化DecorView(FrameLayout)根据情况初始化相应的ViewGroup将ViewGroup添加到DecorView中在ViewGroup中找到Content(FrameLayout)对象将Layout填充到Content中其他操作

以findViewById()为例,来进一步理解

在Activity中,我们使用findViewById()都很熟练,感觉没什么特别的。但是在Framework中,想要找到特定的控件对象,会使用

view.findViewById(id);

来获取相应的控件。实际上,findViewById()是View当中的方法在Activity中,findViewById()实际上是调用DecorView.findViewById(),只是不给使用者展示。也就是说,DecorView是外层的布局,也从侧面验证了上图。

RTFSC解释

为了把握整体思路,这里并没有详细地说明每一行代码

Activity中的相关代码

public void setContentView(@LayoutRes int layoutResID) {
    //会调用PhoneWindow中的代码
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}

PhoneWindow中setContentView()相关代码

public void setContentView(int layoutResID) {
    //mContentParent,也就是Content(上图浅紫色,与Title平级的部分)
    if (mContentParent == null) {
        //DecorView会在这里初始化,ViewGroup也在该方法中添加到DecorView中了,同时找打了mContentParent对象
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }

    if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                getContext());
        transitionTo(newScene);
    } else {
        //将我们的Layout填充到mContentParent中
        mLayoutInflater.inflate(layoutResID, mContentParent);
    }
    mContentParent.requestApplyInsets();
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
        cb.onContentChanged();
    }
}

installDecor()中相关的代码,有省略代码

private void installDecor() {
    if (mDecor == null) {
        //初始化DecorView
        mDecor = generateDecor();
        //一些相关的配置
        mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
        mDecor.setIsRootNamespace(true);
        if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
            mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
        }
    }
    if (mContentParent == null) {
        //将ViewGroup添加到DecorView中,并将Content找到,返回
        mContentParent = generateLayout(mDecor);

        mDecor.makeOptionalFitsSystemWindows();

        //自带装饰的Content
        //DecorContentParent名字起的也很生动,带装饰的
        final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
                R.id.decor_content_parent);

        if (decorContentParent != null) {
            //对decorContentParent的操作
            //设置logo,title,icon,options...
        } else {
            //对Title的一些操作
            //...
        }

        if (mDecor.getBackground() == null && mBackgroundFallbackResource != 0) {
            mDecor.setBackgroundFallback(mBackgroundFallbackResource);
        }

        // Only inflate or create a new TransitionManager if the caller hasn't
        // already set a custom one.
        if (hasFeature(FEATURE_ACTIVITY_TRANSITIONS)) {
            //一些过渡的操作
            //...
        }
    }
}

generateLayout中相关的代码,有省略

protected ViewGroup generateLayout(DecorView decor) {
    //获取相关属性
    TypedArray a = getWindowStyle();

    if (false) {
        //估计是调试用的代码
        //...
    }

    //各种属性的设置
    //...

    //ViewGroup的Layout用的id
    int layoutResource;
    int features = getLocalFeatures();
    //根据设置来确定layoutResource是哪个layout
    //...

    //做个开始标记
    mDecor.startChanging();

    //填充ViewGroup
    View in = mLayoutInflater.inflate(layoutResource, null);
    //将ViewGroup添加到DecorView中
    decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    mContentRoot = (ViewGroup) in;

    //获取Content对象
    ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);

    //一些操作
    //...

    //做个结束标记
    mDecor.finishChanging();

    //返回ViewGroup
    return contentParent;
}

结语

setContentView()相关的代码还是很多的,需要抓住重点,这样才不会影响整体的思维。
如果看完了还是感觉云里雾里,那就先把图片记住,剩下的以后再说

转载请标明出处:http://blog.csdn.net/qq_26411333/article/details/51541129

版权声明:本文为博主原创文章,未经博主允许不得转载。

从源码角度剖析 setContentView() 背后的机制

注:本文基于 AS 2.3,示例中的 Activity 继承自 AppcompatActivity。 示例 源码解析 AppCompatDelegateImplV7 PhoneWindow 流程一览...
  • ziwang_
  • ziwang_
  • 2017年03月28日 19:09
  • 581

Android源码解析Activity#setContentView()方法

在Activity初始化的过程中,会调用Activity的attach方法,在该方法中会创建一个PhoneWindow的实例,将其作为Activity的mWindow成员变量。在执行完了Activit...
  • sunqunsunqun
  • sunqunsunqun
  • 2016年07月27日 11:13
  • 6614

Android 源码解析 之 setContentView

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/41894125,本文出自:【张鸿洋的博客】大家在平时的开发中,对于setConte...
  • lmj623565791
  • lmj623565791
  • 2014年12月16日 15:19
  • 33146

Android应用setContentView与LayoutInflater加载解析机制源码分析

【工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处,尊重分享成果】1 背景其实之所以要说这个话题有几个原因: 理解xml等控件是咋被显示的原理,通常大家写代码都...
  • yanbober
  • yanbober
  • 2015年05月26日 23:16
  • 40188

(4.1.37.1)深入理解setContentView过程和View绘制过程

一Android屏幕层级 1 Window概念 11 PhoneWindow 二setContentView过程 三View绘制前过程 1 ViewRoot 2 View绘制的起点 四 View绘制 ...
  • fei20121106
  • fei20121106
  • 2017年11月02日 17:39
  • 486

理解setContentView的作用

android学习小结-setContentView的作用
  • fjz2014
  • fjz2014
  • 2015年07月02日 22:08
  • 521

浅谈Activity中setContentView()

引言 找入口 PhoneWindow类中相关代码解读 installDecor generateLayout 总结一下引言今天来研究一下Android中setContentView()方法的具体实现。...
  • wenwen091100304
  • wenwen091100304
  • 2015年10月23日 21:31
  • 5183

谈谈activity中setContentView()内部的实现。

在安卓的开发中,每当我们新建一个activity,其中一个必不可少的步骤就是setContentView()。那么安卓系统是怎么把布局文件加载进来的呢,这里简单的分析下源码。这里我继承的是AppCom...
  • wglla
  • wglla
  • 2016年08月11日 00:36
  • 827

setContentView( )的简单用法

setContentView(R.layout.main)在Android里面 R.layout.main是个布局文件即控件都是如何摆放如何显示的,setContentView就是设置一个Activ...
  • zsr251
  • zsr251
  • 2014年09月11日 22:15
  • 631

android之论setContentView(R.layout.activity_main)位置的重要性

时间:2017/3/16       首先声明我是一个Android开发刚入门的菜鸟,只是了解android基本控件及开发步骤。今天尝试开发一款基于android的点菜App,然而在第一个登陆界面就...
  • tpkAaron
  • tpkAaron
  • 2017年03月16日 16:18
  • 1231
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:setContentView()源码的理解
举报原因:
原因补充:

(最多只允许输入30个字)