Android源码阅读分析:从资源文件到控件布局——LayoutInflater分析

本文详细探讨了Android的LayoutInflater如何将资源文件转换为控件布局。通过分析构造方法,尤其是通过Context和getSystemService获取LayoutInflater的方式,揭示了 LayoutInflater 的工作原理。接着,文章深入解析了构建View的过程,包括解析XML布局、实例化控件等关键步骤,指出自定义控件需具备的构造方法。最后,总结了从布局XML到控件实例化的完整流程。
摘要由CSDN通过智能技术生成

从资源文件到控件——LayoutInflater分析


本文也发布于本人的知乎文章:https://zhuanlan.zhihu.com/p/394073666
(注:源代码为android-8.1)

0. 前言

我在我的文章《Android源码阅读分析:从Activity开始(二)——加载布局》中简单介绍了Activity的如何加载布局的。在文章末尾提到,资源文件通过inflater方法转换为View。那么本篇文章就来分析一下LayoutInflater是如何工作的。

1. 创建LayoutInflater

LayoutInflater的构造方法被protected修饰,也就是说,我们在创建LayoutInflater时,不能直接使用构造方法来创建新对象。官方的推荐获取LayoutInflater对象方式有两个:
  - 通过Activity.getLayoutInflater方法获取
  - 通过Context.getSystemService方式获取
这样能够保证获取到的LayoutInflater对象是已经与当前context关联上。那么,我就分别从这两个方法来看一下是如何获取对象的。

1.1 通过Activity.getLayoutInflater获取LayoutInflater对象
(frameworks/base/core/java/android/app/Activity.java)

public LayoutInflater getLayoutInflater() {
   
	return getWindow().getLayoutInflater();
}

从上一篇文章中,我们知道了,Activity.getWindow方法所得到的是一个PhoneWindow对象,那么跟踪PhoneWindowgetLayoutInflater方法。

(framework/base/core/java/com/android/internal/policy/PhoneWindow.java)

public LayoutInflater getLayoutInflater() {
   
	return mLayoutInflater;
}

哦?这里就是简简单单的返回了mLayoutInflater。那么,我们就要看看这个变量是在哪里创建或者赋值的。
  经过查找,发现在PhoneWindow类里,只有一个地方是mLayoutInflater变量被赋值了。

(frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java)

public PhoneWindow(Context context) {
   
	super(context);
	mLayoutInflater = LayoutInflater.from(context);
}

这里调用了LayoutInflaterfrom方法。

(frameworks/base/core/java/android/view/LayoutInflater.java)

public static LayoutInflater from(Context context) {
   
	LayoutInflater LayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	if (LayoutInflater == null) {
   
		throw new AssertionError("LayoutInflater not found.");
	}
    return LayoutInflater;
}

可以看出,这里调用了context.getSystemService方法,这与官方推荐的第二种方法相同。

1.2 通过Context.getSystemService方式获取LayoutInflater对象

getSystemServiceContext的一个方法,通过传入NAME来获取对应的Object,然后转换为相应的服务对象。这里传入的参数值为Context.LAYOUT_INFLATER_SERVICE。通过查找,在ContextThemeWrapper类中找到处理Context.LAYOUT_INFLATER_SERVICE的方法。

(frameworks/base/core/java/androidview/ContextThemeWrapper.java)

@Override
public Object getSystemService(String name) {
   
	if (LAYOUT_INFLATER_SERVICE.equals(name)) {
   
		if (mInflater == null) {
   
			mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
        }
        return mInflater;
    }
    return getBaseContext().getSystemService(name);
}

这里又调用了from(getBaseContext),而baseContext通常情况下就是ContextImpl。那么跟踪到ContextImplgetSystemService方法。

(frameworks/base/core/java/android/app/ContextImpl.java)

@Override
public Object getSystemService(String name) {
   
	return SystemServiceRegistry.getSystemService(this, name);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

董小虫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值