在Activity的生命周期onCreate中。我们一般都习惯性的调用setContentView(int layoutResID)方法,把布局文件载入到页面上来。以下我们就来通过源代码一步步的分析怎么载入的。

在Activity中,调用的是Window的setContentView

public void setContentView(int layoutResID) {

        getWindow().setContentView(layoutResID);

        initWindowDecorActionBar();

    }

我们通过源代码发现Window是一个抽象类。并且 getWindow()返回的仅仅是一个mWindow。

public Window getWindow() {

        return mWindow;

    }

那么mWindow是在什么地方初始化的。我们继续查看源代码,终于发现是在一个叫attach的方法中调用,但是终于我们没有发现调用attach的方法,事实上这种方法是在ActivityThread这个类中调用的。这个类非常重要,包含在main方法中初始化Looper,在这里先不说,以后在介绍。

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

…………

            Activity activity = null;

            activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);

…………

Application app = r.packageInfo.makeApplication(false, mInstrumentation);

…………

activity.attach(appContext, this, getInstrumentation(), r.token,

                        r.ident, app, r.intent, r.activityInfo, title, r.parent,

                        r.embeddedID, r.lastNonConfigurationInstances, config);

…………

        return activity;

    }

接着我们在attach方法中看到这样一行代码

mWindow = PolicyManager.makeNewWindow(this);

继续查看,找到PolicyManager这个类,

private static final String POLICY_IMPL_CLASS_NAME =

        "com.android.internal.policy.impl.Policy";

…………

            Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);

            sPolicy = (IPolicy)policyClass.newInstance();

  …………

    public static Window makeNewWindow(Context context) {

        return sPolicy.makeNewWindow(context);

    }

继续,在Policy这个类中我们找到

public Window makeNewWindow(Context context) {

        return new PhoneWindow(context);

    }

也就是说最初我们找到mWindow就是PhoneWindow,我们继续。不要闲着,

public class PhoneWindow extends Window implements MenuBuilder.Callback

我们通过源代码发现PhoneWindow事实上就是Window。先回到我们刚才说的

getWindow().setContentView(layoutResID);这种方法,事实上就是调用PhoneWindow的setContentView(layoutResID);方法。我们通过源代码继续查看

@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();

        }

    }

我们先简单分析一下下半部分。假设Callback不为空且没有被销毁的情况下会调用onContentChanged()方法。通过源代码我们发现事实上Activity是实现了Callback接口的

public class Activity extends ContextThemeWrapper

        implements LayoutInflater.Factory2,

        Window.Callback, KeyEvent.Callback,

        OnCreateContextMenuListener, ComponentCallbacks2,

        Window.OnWindowDismissedCallback

并且在onContentChanged()方法中是空实现,什么都没做。

public void onContentChanged() {

    }

我们再来分析上半部分,假设mContentParent 不为空的话,首先移除全部的子View,removeAllViews方法是ViewGroup类中,View中没有。我们能够先大致看一下。以后在做具体介绍

/**

     * Call this method to remove all child views from the

     * ViewGroup.

     * 

     * <p><strong>Note:</strong> do not invoke this method from

     * {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)},

     * {@link #dispatchDraw(android.graphics.Canvas)} or any related method.</p>

     */

    public void removeAllViews() {

        removeAllViewsInLayout();

        requestLayout();

        invalidate(true);

    }

假设mContentParent 为空的话,调用  installDecor();进行初始化,接着我们看一下  installDecor();方法的详细实现。

private void installDecor() {

        if (mDecor == null) {

            mDecor = generateDecor();

          …………

        }

        if (mContentParent == null) {

            mContentParent = generateLayout(mDecor);



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

         …………

                mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);

…………

        }

    }

首先推断mDecor是否为空,假设为空就调用 generateDecor();我们接着看它详细怎么实现

protected DecorView generateDecor() {

        return new DecorView(getContext(), -1);

    }

我们发现就一行代码,那么DecorView又是什么,我们继续查看,

private final class DecorView extends FrameLayout implements RootViewSurfaceTaker

最终找到了,原来继承的是FrameLayout ,看到这里可能有的人会恍然大悟,由于我们知道在Activity的setContentView中载入的根布局事实上就是FrameLayout 。这里的FrameLayout 有两部分组成,一部分是系统自定义的title。一部分是content,就是我们自定义的布局,还有,在之前假设我们不须要title的话,我们会在AcdroidMainfest中 android:theme="@android:style/Theme.NoTitleBar",或者在activity中设置requestWindowFeature(Window.FEATURE_NO_TITLE);可是要设置在setContentView之前,好了,上面的代码我们先分析到这,以后有时间还会接着继续写。欢迎拍砖。

Android setContentView方法解析(一)的更多相关文章

  1. 【Android 多媒体开发】 MediaPlayer 状态机 接口 方法 解析

    作者 : 韩曙亮 转载请著名出处 :  http://blog.csdn.net/shulianghan/article/details/38487967 一. MediaPlayer 状态机 介绍 ...

  2. Android Service完全解析,关于服务你所需知道的一切(下)

    转载请注册出处:http://blog.csdn.net/guolin_blog/article/details/9797169 在上一篇文章中,我们学习了Android Service相关的许多重要 ...

  3. Android Service完全解析,关于服务你所需知道的一切(上)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11952435 相信大多数朋友对Service这个名词都不会陌生,没错,一个老练的A ...

  4. Android IntentService完全解析 当Service遇到Handler

    一 概述 大家都清楚,在Android的开发中,凡是遇到耗时的操作尽可能的会交给Service去做,比如我们上传多张图,上传的过程用户可能将应用置于后台,然后干别的去了,我们的Activity就很可能 ...

  5. android源码解析(十七)-->Activity布局加载流程

    版权声明:本文为博主原创文章,未经博主允许不得转载. 好吧,终于要开始讲讲Activity的布局加载流程了,大家都知道在Android体系中Activity扮演了一个界面展示的角色,这也是它与andr ...

  6. Android实现XML解析技术

    转载:Android实现XML解析技术 本文介绍在Android平台中实现对XML的三种解析方式. XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为 ...

  7. 36、Android Bitmap 全面解析

    Android Bitmap 全面解析(一)加载大尺寸图片 http://www.eoeandroid.com/thread-331669-1-1.html Android Bitmap 全面解析(二 ...

  8. 【转】Android Service完全解析,关于服务你所需知道的一切(下) ---- 不错

    原文网址:http://blog.csdn.net/guolin_blog/article/details/9797169 转载请注册出处:http://blog.csdn.net/guolin_bl ...

  9. Android ActionBar完全解析,使用官方推荐的最佳导航栏(上)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/18234477 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工 ...

随机推荐

  1. SpringMVC知识一锅烩

    Spring简介 SpringMVC和Struts2一样都是属于表现层的框架,将前段发出的请求分发给对应的后端处理器即Controller 处理流程 用户请求被前端控制前拦截,然后根据对应的拦截路径去 ...

  2. 一个简单的基于BIO的RPC框架

    github地址:https://github.com/Luyu05/BioRpcExample PART1:先来整体看下项目的构成 其中bio-rpc-core就是所谓的rpc框架 bio-rpc- ...

  3. for循环中执行setTimeout问题

    代码片段: for(var i=0;i<8;i++){ setTimeout(function () { console.log(i) },0) } 输出了8次8,这跟js的执行顺序和作用域链有 ...

  4. DIY 温控烙铁

    由于工艺原因,某处要使用200W大功率烙铁(恒温烙铁虽然有那么大功率,但没有那么大的烙铁头),只能选用普通电热丝烙铁(无温控),存在温度过高现象(造成工艺不良,同时因助焊剂+高温造成烙铁头腐蚀),逐渐 ...

  5. c#鼠标点击TextBox控件后清空默认字体

    方案(一) 脚本: <script type="text/javascript" language="javascript">        //得 ...

  6. R学习笔记 第五篇:字符串操作

    文本数据存储在字符向量中,字符向量的每个元素都是字符串,而非单独的字符.在R中,可以使用双引号,或单引号表示字符,函数nchar用于获得字符串中的字符数量: > s='read' > nc ...

  7. python基础-------函数(一)

    一 为何要有函数?不加区分地将所有功能的代码垒到一起, 问题是: 代码可读性差 代码冗余 代码可扩展差 如何解决?函数即工具,事先准备工具的过程是定义函数,拿来就用指的就是函数调用 结论:函数使用必须 ...

  8. python调用c代码

    Linux环境下使用python调用C的printf例子: #!/usr/bin/env python2.7 #-*- coding:utf-8 -*- from ctypes import * de ...

  9. [转]SQL Server 表变量和临时表的区别

    一.表变量 表变量在SQL Server 2000中首次被引入.表变量的具体定义包括列定义,列名,数据类型和约束.而在表变量中可以使用的约束包括主键约束,唯一约束,NULL约束和CHECK约束(外键约 ...

  10. JMS学习之路(一):整合activeMQ到SpringMVC 转载:http://www.cnblogs.com/xiaochangwei/p/5426639.html

    JMS的全称是Java Message Service,即Java消息服务.它主要用于在生产者和消费者之间进行消息传递,生产者负责产生消息,而消费者负责接收消息.把它应用到实际的业务需求中的话我们可以 ...