文章来自https://github.com/NieJianJian/AndroidNotes,内容将持续更新,欢迎star。
1. LayoutInflater使用场景
LayoutInflater我们都用到过,比如在RecyclerView中加载一个View:
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.fruit_item, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
根据上面的内容,我们可以明白,LayoutInflater会通过inflate方法会创建一个View并返回。
LayoutInflater的作用和findViewById类似,不同的是findViewById是根据查找xml布局内id来返回相应的widget控件(如Button、TextView)。LayoutInflater的inflate方法是将xml文件转换成View。
比如我们的setContentView:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
还可以这样写:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = LayoutInflater.from(this).inflate(R.layout.activity_main,
(ViewGroup) findViewById(android.R.id.content), false);
setContentView(view);
}
为什么可以这样写?我们来看下setContentView的源码:
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
getWindow得到的了PhoneWindow,所以调用PhoneWindow的setContentView,我们继续往下看:
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
...
}
在PhoneWindow的setContentView中,就调用了Layout.inflate方法。
2. 获取LayoutInflater实例的方法和原理。
获得LayoutInflater实例的方式有以下三种:
LayoutInflater inflater = getLayoutInflater();
LayoutInflater inflater = LayoutInflater.from(this);
LayoutInflater inflater2 = (LayoutInflater)
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
其实这三种方式的本质是相同的
Activity的getLayoutInflater()方法:
public LayoutInflater getLayoutInflater() {
return getWindow().getLayoutInflater();
}
然后是PhoneWindow的getLayoutInflater方法:
public LayoutInflater getLayoutInflater() {
return mLayoutInflater;
}
那mLayoutInflater是什么时候赋值的呢?来看PhoneWindow的构造方法:
public PhoneWindow(Context context) {
super(context);
mLayoutInflater = LayoutInflater.from(context);
}
所以看出,Activity的getLayoutInflater()最终调用的就是第二种方法。
接着看LayoutInflater.from方法:
public static LayoutInflater from(Context context) {
LayoutInflater LayoutInflater =
(LayoutInflater) context.getSystemService(Context