获取LayoutInflater的三种方式分析

对于LayoutInflater的定义,我们来看一下官方文档,
Instantiates a layout XML file into its corresponding android.view.View objects.
意思是,将一个XML文件实例化为对应的View对象。

在实际开发中,我们避免不了需要使用到LayoutInflater类中的inflate()方法。对于LayoutInflater对象的获取,有三种方式。

LayoutInflater inflater = 
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);// 第一种方式

LayoutInflater inflater = LayoutInflater.from(context);// 第二种方式

LayoutInflater inflater = activity.getLayoutInflater();// 第三种方式

那么这三种方式有什么区别呢?

(1).第一种方式
getSystemService()是Android很重要的一个API,它是Context类的一个方法,根据传入的name来取得对应的Object,然后转换成相应的服务对象。Context.LAYOUT_INFLATER_SERVICE表示我们取得的是实例化layout的服务对象。

(2).第二种方式
我们来看一下它的内部实现。

/**
 * Obtains the LayoutInflater from the given 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;
}

from()是LayoutInflater中的一个静态方法,返回LayoutInflater对象。我们可以看到,方法内部其实使用的是context.getSystemService(),也就是上述第一种方式。

(3).第三种方式
getLayoutInflater()是Activity类的一个方法,也就是说只有通过Activity类的引用才能调用,相比于第一种和第二种方式,此种方式存在一定的使用局限。我们来看一下它的内部实现。

Activity类的关键代码

package android.app;

public class Activity extends ContextThemeWrapper implements ... {
    ......
    private Window mWindow;
    ......

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

    public Window getWindow() {
        return mWindow;
    }

    final void attach(...) {
        ......
        mWindow = new PhoneWindow(this);
        ......
    }

    ......
    ......
}

从源码可以看到,当我们调用getLayoutInflater()方法时,方法内部先调用了getWindow()方法,而getWindow()返回的是Activity类的mWindow成员变量,mWindow是Window类的引用。当Activity被创建时,会调用attach()方法,在attach()方法里面完成mWindow成员变量赋值,mWindow实际上是PhoneWindow类的对象。Window是一个抽象类,其内部的getLayoutInflater()方法是abstract的,PhoneWindow类继承自Window类,实现了getLayoutInflater()方法,即我们最终调用的是PhoneWindow类的getLayoutInflater()方法。

Window类的关键代码

package android.view;

public abstract class Window {

    ......

    @NonNull
    public abstract LayoutInflater getLayoutInflater();

    ......

}

PhoneWindow类的源码SDK并未给我们提供,从Android源码中我们可以找到PhoneWindow类的实现,路径\platform_frameworks_base-master\core\java\com\android\internal\policy\PhoneWindow.java。

PhoneWindow类的关键代码

package com.android.internal.policy;

public class PhoneWindow extends Window implements MenuBuilder.Callback {

    ......

    private LayoutInflater mLayoutInflater;

    ......

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

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

    ......
}

到这里,真相大白了。PhoneWindow类的getLayoutInflater()方法,内部使用的其实是LayoutInflater.from(context),即上述第二种方式。

**结论:
获取LayoutInflater对象,最终都是通过调用Context类的getSystemService()方法来实现的。**

你可能感兴趣的:(Android基础)