四种布局填充器的区别,以及对应的设计模式

Android的xml布局文件是不能直接显示在手机界面上的,手机界面上能够显示的只有视图(View),若要使xml布局文件显示在手机页面上就必须将xml文件转化为视图,进行xml解析,下面是几种转化方法。

//1.通过Activity中的getLayoutInflater()方法
 View view = getLayoutInflater().inflate(resource, root, attachToRoot);

 //2.通过系统服务获取布局加载器
 LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 View view = inflater.inflate(resource, root, attachToRoot);

 //3.通过View的静态inflate()方法
 View view = View.inflate(resource, root, attachToRoot);

 //4.通过LayoutInflater的inflate()方法
 View view = LayoutInflater.from(context).inflate(resource, root, attachToRoot);

1 Activity中的的getLayoutInflater()

我们先来分析Activity的getLayoutInflater()

@NonNull
public LayoutInflater getLayoutInflater() {
    //这里直接去看phoneWindow中的getLayoutInflater();
    return getWindow().getLayoutInflater();
}

//我们可以看到,这里在phoneWindow的构造方法中就有LayoutInflater.form(context).
public PhoneWindow(Context context) {
    super(context);
    mLayoutInflater = LayoutInflater.from(context);
}
1
2
3
4
而我们知道在Activity中,phonewindow的初始化
则是在setContentView中进行了初始化。
所以得到结论 getLayoutInflater的本质就是LayoutInflater.from()
也就是1<==>4

2.通过系统服务获取加载器getSystemService()

@Override
public Object getSystemService(@ServiceName @NonNull String name) {
    if (WINDOW_SERVICE.equals(name)) {
        return mWindowManager;
    } else if (SEARCH_SERVICE.equals(name)) {
        ensureSearchManager();
        return mSearchManager;
    }
    //这里因为传入的string是"layout_inflater",所以会直接调用super方法。
    //也就是直接到ContextThemeWrapper方法中的getSystemService
    return super.getSystemService(name);
}

@Override
public Object getSystemService(String name) {
    //String是相等的
    if (LAYOUT_INFLATER_SERVICE.equals(name)) {
        if (mInflater == null) {
            //内部还是调用的layoutInflater.from方法,直接clone了一个context而已。  
            mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
        }
        return mInflater;
    }
    return getBaseContext().getSystemService(name);
}
1
2
总结:getSystemService的内部还是在调用LayoutInflater.from()
也就是2<==>4

3 通过View的静态inflate()方法

public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
    //依旧是通过layoutInflater.from()
    LayoutInflater factory = LayoutInflater.from(context);
    //这里的inflate实际上就是进行xml解析
    return factory.inflate(resource, root);
}
1
2
总结:通过View的静态inflate()的内部在调用LayoutInflater.from()
也就是3<==>4

4. 通过LayoutInflater的inflate()方法

我们既然知道 四种方法,内部 实际上都是在调用LayoutInflater.from(context),那么这里就需要着重对这段源码来进行分析。

/**
 * Obtains the LayoutInflater from the given context.
 */
public static LayoutInflater from(Context context) {
    LayoutInflater LayoutInflater =
          //这里就很奇怪,内部是getSystemService,又回到了系统服务获取加载器。
            (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if (LayoutInflater == null) {
        throw new AssertionError("LayoutInflater not found.");
    }
    return LayoutInflater;

而inflate 则实际上就是xml解析的过程。

我们是否对这种方式感到诧异?
getlayoutinflater()最终调用的是layoutinflater.from,里面又调用的getSystemService,而getSystemService内部则又是调用了
LayoutInflater.from(getBaseContext());

其实这个LayoutInflater就涉及到单例模式

igding wechat
2018 依计行事 持续精进
坚持原创技术分享,您的支持将鼓励我继续创作!