Android学习笔记:浅析setContentView

本文主要探讨了Android中setContentView的工作原理,从Activity的源码分析了setContentView的重载方法,尤其是setContentView(int layoutResId)。通过一步步跟踪源码,解释了布局文件如何被加载到Activity中,涉及PhoneWindow、DecorView、LayoutInflater等多个关键概念,帮助读者理解XML布局到Activity的加载过程。
摘要由CSDN通过智能技术生成

  每次在Github上看到炫酷效果的demo时,都会想,什么时候自己也能实现这样的效果。要想有所收获,就必须得付出。于是,我决定花时间来学习自定义View,虽说自定义View水很深,但凡事得一步步来,终会有所收获的。要实现自定义View,必须得先了解View的绘制流程,但在学习View的绘制流程之前,先来了解下setContentView这个方法时如何将XML布局加载到当前Activity?

  从Activity源码可以看出,setContentView方法有三个重载方法,分别是:

  • setContentView(int layoutResId):将布局文件加载到当前Activity,并且在Activity充当父布局角色。

  • setContentView(View view):将View加载到当前Activity。当调用这个方法设置View时,自己对View设置布局参数宽高会被忽略,默认的宽高是android.view.ViewGroup.LayoutParams.MATCH_PARENT。如果想使用自己定义的布局参数,可以使用setContentView(View view, ViewGroup.LayoutParams params)这个方法代替。

  • setContentView(View view, ViewGroup.LayoutParams params):将View加载到当前Activity。

从源码来看,这个三个重载方法的实现逻辑都差不多,所以我只分析setContentView(int layoutResId).

Step 1

  进入到Activity源码,找到setContentView(int layoutResId)方法如下:

public void setContentView(int layoutResID) {
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();

只有两行代码,有木有一种挺简单的感觉。其实不然,往下看就知道有多复杂了。从第2行看起,进入getWindow()这个方法,代码如下

public Window getWindow() {
    return mWindow;
}

获取Activity当前Window对象,Window是抽象类,不能实例化对象,那么是怎么获取到Window对象?在Activity源码中attach方法有这样的一行代码

mWindow = PolicyManager.makeNewWindow(this);

很明显,这是获取Window对象的,继续往下看。进入PolicyManagermakeNewWindow()方法

public static Window makeNewWindow(Context context) {
    return sPolicy.makeNewWindow(context);
}

那么sPolicy又是什么呢,代码如下:

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);
    }
}

从以上代码可以看出,IPolicy是接口,通过反射机制获取到sPolicy,该接口的实现类是Policy,所以定位到该类makeNewWindow()方法

public Window makeNewWindow(Context context) {
    return new PhoneWindow(context);
}

终于获取到Window对象,该对象的类型是

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值