LayoutInflater 加载布局文件原理,过程分析

       工作之余,研究了一下Android系统的源码,准备这段时间写几篇文章做一下总结,有问题的话欢迎批评指正,本篇文章先针对LayoutInflater加载布局的过程以及原理做一些分析,网上也有不少的相关的文章,也感谢优秀的Android大牛们的分享,为我们平时的开发以及学习提供了很好的借鉴。

      感谢 http://blog.csdn.net/a740169405/article/details/54580347链接的作者,为我们提供了比较好的LayoutInflater分析的相关思路。

      话不多说,下面开始:

      文章的重点会放在LayoutInflater加载布局文件的原理以及过程上,这里稍微提一下LayoutInflater的获取方式:

方式一:通过Context的getSystemService(String name)方法,熟悉Context的朋友应该知道,Context是一个抽象类,它有两个实现类ContextWrapper和ContextImpl,我们来看下ContextWrapper的getSystemService()方法

@Override
    public Object getSystemService(String name) {
        return mBase.getSystemService(name);
    }

我们可以看到,该方法内部调用了mBase.getSystemService()的方法,这个mBase是ContextImpl类的对象,在这里我就不解释为什么是ContextImpl类的对象了,因为这不是本文的重点,考虑以后有时间写一篇专门介绍Context的文章,在这里知道就行了。我们来看下ContextImpl类的getSystemService()方法:

@Override
    public Object getSystemService(String name) {
        return SystemServiceRegistry.getSystemService(this, name);
    }

我用android sdk版本是26,不同的sdk版本ContextImpl中getSystemService()方法的实现可能不太一样,我们再来看一下SystemServiceRegistery.getSystemService()方法的源码

public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }

不管使用的sdk版本是多少,但是最终应该都会调用到上述代码来获取LayoutInflater对象,这里简单说一下,SYSTEM_SERVICE_FETCHERS是一个HasMap对象,存储了很多的服务 ,准确的说,是存储了很多服务的获取器,就是ServiceFetcher,通过获取器的getService方法,最终获取到对应的服务,除了LayoutInflater之外,还有WindowManager、ActivityManager等等。

方法二:通过LayoutInflater.from(Context context)来获取,我们来看下该方法的代码

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(String name)方法来获取对象

方法三:如果是在Activity中,可以通过Activity的getLayoutInflater方法获取,我们来看下该方法的代码

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

getWindow()获得一个Window的对象,Window的实现类时PhoneWindow,我们来看下PnhoneWindow的getLayoutInflater()方法

@Override
    public LayoutInflater getLayoutInflater() {
        return mLayoutInflater;
    }

该方法直接return了一个LayoutInflater的对象,该对象是在PhoneWindow的构造方法里创建的

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

可以看到在PhoneWindow的构造方法里面,是通过LayoutInflater.from(Context)来获得的一个LayoutInflater对象

因此上述三种方法最终都是通过Context.getSystemService()来获得的LayoutInflater对象。

下面我们来看一下LayoutInflater是怎么把xml文件转换成View的:

入口是LayoutInflater的inflate()方法,inflater有四个不同的实现方法

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root)
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)
public View inflate(XmlPullParser parser, @Nullable ViewGroup root)
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)

下面我们以public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) 为例,来分析一下LayoutInflater把xml文件转换成View的原理和过程

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
        return inflate(resource, root, root != null);
    }

我们可以看到在该方法的内部又调用了另一个三个参数的inflate方法

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
        final Resources res = getContext().getResources();
        if (DEBUG) {
            Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
                    + Integer.toHexString(resource) + ")");
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值