android:layout_width=
“match_parent”
android:layout_height=
“match_parent”
tools:context=
“.MainActivity”>
<TextView
android:id=
“@+id/tv_text”
android:layout_width=
“wrap_content”
android:layout_height=
“wrap_content”
android:text=
“Hello World!”
app:layout_constraintBottom_toBottomOf=
“parent”
app:layout_constraintLeft_toLeftOf=
“parent”
app:layout_constraintRight_toRightOf=
“parent”
app:layout_constraintTop_toTopOf=
“parent” />
<include
android:id=
“@+id/layout_include”
layout=
“@layout/layout_comment” />
</androidx.constraintlayout.widget.ConstraintLayout>
那么此时我们如何使用到layout_comment.xml布局中的TextView控件呢,首先include标签需要声明id,例如layout_include,然后Activity中代码如下:
mBinding.layoutInclude.tvInclude.setText("这就是你的不对了");
是不是很神奇,是不是很简单。
注意:
当你给layout_comment.xml的根布局再添加id(比如添加了layout_xxx的ID)的时候,此时会报错:
java.lang.NullPointerException: Missing required view with ID: layout_xxx
3.3.2、布局中使用include和merge
我们将上文的layout_comment.xml稍作修改,根布局使用merge标签,其他不做修改:
<merge xmlns:android=
“http://schemas.android.com/apk/res/android”
android:layout_width=
“match_parent”
android:layout_height=
“wrap_content”>
<TextView
android:id=
“@+id/tv_include”
android:text=
“这就是测试啊”
android:gravity=
“end”
android:layout_width=
“match_parent”
android:layout_height=
“match_parent” />
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=
“http://schemas.android.com/apk/res/android”
xmlns:app=
“http://schemas.android.com/apk/res-auto”
xmlns:tools=
“http://schemas.android.com/tools”
android:layout_width=
“match_parent”
android:layout_height=
“match_parent”
tools:context=
“.MainActivity”>
<include
android:id=
“@+id/layout_include”
layout=
“@layout/layout_comment” />
</androidx.constraintlayout.widget.ConstraintLayout>
activity_main.xml文件中使用include添加该布局后,在java代码中依旧是可以正常使用以下代码的:
mBinding.layoutInclude.tvInclude.setText("会不会出现问题呀");
但是但是!!!运行就会报错:
java.lang.NullPointerException: Missing required view with ID: layoutInclude
要是把include标签的id去掉的话,这时mBinding中也是找不到tvInclude这个控件呀,怎么办??
之前是不是说过,每个layout文件都会对应一个Binding文件,那么layout_comment.xml,肯定也有一个LayoutCommentBinding.java文件,我们去看下这个文件的源代码,里面有个可疑的方法,bind()方法:
@NonNull
public static LayoutCommentBinding bind(@NonNull View rootView) {
// The body of this method is generated in a way you would not otherwise write.
// This is done to optimize the compiled bytecode for size and performance.
String missingId;
missingId: {
TextView tvInclude = rootView.findViewById(R.id.tv_include);
if (tvInclude ==
null) {
missingId =
“tvInclude”;
break missingId;
}
return
new LayoutCommentBinding(rootView, tvInclude);
}
throw
new NullPointerException(
"Missing required view with ID: ".concat(missingId));
}
所以对于含有merge标签的布局我们可以使用bind()方法来绑定到根布局上,在这里,根布局就是mBinding.getRoot()了。所以代码如下:
//这么写不可以
//mBinding.layoutInclude.tvInclude.setText(“会不会出现问题呀”);
LayoutCommentBinding commentBinding = LayoutCommentBinding.bind(mBinding.getRoot());
commentBinding.tvInclude.setText(
“这就不会出现问题了吧”);
同时需要注意: include标签不可以有id
3.4、Fragment中使用ViewBinding
在Fragment的**onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)**方法中:
//原来的写法
return inflater.inflate(R.layout.fragment_blank, container,
false);
//使用ViewBinding的写法
mBinding = FragmentBlankBinding.inflate(inflater);
return mBinding.getRoot();
拿到FragmentBlankBinding的对象后,更新数据的都和之前一样了。
3.5、自定义View中使用ViewBinding
这里直接贴出来代码吧,就是自定义了一个Fragment然后往其中添加了一个布局,该布局是上文的layout_comment.xml文件,会生成一个对应的LayoutCommentBinding.java文件,同样可以直接使用:
public
class MyView extends FrameLayout {
LayoutCommentBinding commentBinding;
public MyView(@NonNull Context context) {
this(context,
null);
}
public MyView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs,
0);
}
public MyView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initLayout();
}
private void initLayout() {
//之前的写法
//View view = LayoutInflater.from(getContext()).inflate(R.layout.layout_comment, this, false);
//addView(view);
//使用ViewBinding的写法
commentBinding = LayoutCommentBinding.inflate(LayoutInflater.from(getContext()),
this,
false);
addView(commentBinding.getRoot());
}
public void setText(String str) {
commentBinding.tvInclude.setText(str);
}
}
3.6、Adapter中使用ViewBinding
在RecyclerView结合Adapter的例子中我们再使用ViewBinding来尝试下,直接贴Adapter的代码:
public
class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> {
private List mList;
public MainAdapter(List list) {
mList = list;
}
@NonNull
@Override
this(context,
null);
}
public MyView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs,
0);
}
public MyView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initLayout();
}
private void initLayout() {
//之前的写法
//View view = LayoutInflater.from(getContext()).inflate(R.layout.layout_comment, this, false);
//addView(view);
//使用ViewBinding的写法
commentBinding = LayoutCommentBinding.inflate(LayoutInflater.from(getContext()),
this,
false);
addView(commentBinding.getRoot());
}
public void setText(String str) {
commentBinding.tvInclude.setText(str);
}
}
3.6、Adapter中使用ViewBinding
在RecyclerView结合Adapter的例子中我们再使用ViewBinding来尝试下,直接贴Adapter的代码:
public
class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> {
private List mList;
public MainAdapter(List list) {
mList = list;
}
@NonNull
@Override