用于 Data-bindng 的模板文件,是由 data
节点 跟 layout
节点组成.
一个简单的示例如下:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.example.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastName}"/>
</LinearLayout>
</layout>
使用上来说,如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityDataBindingBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_data_binding);
binding.setUser( new User("Haizhen","Lee"));
}
然后就OK了, 以前繁杂的findViewById
的调用,及设置值
与普通的 ViewHolder有所区别, 保存一个 Binding应该是比较好的选择:
class UserViewHolder extends RecyclerView.ViewHolder {
private RecyclerListItemBinding mBinding;
public UserViewHolder(RecyclerListItemBinding binding) {
super(binding.getRoot());
mBinding = binding;
}
public void bind(User user){
mBinding.setUser(user);
}
}
然后修改RecyclerViewAdapter如下:
class DemoRecyclerViewAdapter extends RecyclerView.Adapter<UserViewHolder>{
private List<User> userList;
private static final int layoutId = R.layout.recycler_list_item;
public DemoRecyclerViewAdapter(List<User> users){
this.userList = users;
}
@Override
public UserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
RecyclerListItemBinding binding = DataBindingUtil.inflate(layoutInflater,layoutId,parent,false);
return new UserViewHolder(binding);
}
@Override
public void onBindViewHolder(UserViewHolder holder, int position) {
User user = userList.get(position);
holder.bind(user);
}
@Override
public int getItemCount() {
return userList.size();
}
}
ActvityDataBindingBinding 怎么来的?
这是 Android 编译系统 根据布局文件名 activity_data_binding.xml
生成的
是编译期动态生成类
DataBindingUtil 做了什么?
查看源代码如下:
public static <T extends ViewDataBinding> T setContentView(Activity activity, int layoutId) {
View decorView = activity.getWindow().getDecorView();
ViewGroup contentView = (ViewGroup)decorView.findViewById(16908290);
ViewDataBinding binding = inflate(activity.getLayoutInflater(), layoutId, contentView, false);
activity.setContentView(binding.getRoot(), binding.getRoot().getLayoutParams());
return binding;
}
可以看到绑定User
对象的操作在 executeBindings
中进行.
@Override
protected void executeBindings() {
long dirtyFlags = 0;
synchronized(this) {
dirtyFlags = mDirtyFlags;
mDirtyFlags = 0;
}
java.lang.String firstNameUser = null;
java.lang.String lastNameUser = null;
com.banxi1988.v2exgeek.demo.User user = mUser;
if ((dirtyFlags & 0b11L) != 0) {
// read firstName~.~user~
if ( user != null) {
firstNameUser = user.firstName;
}
// read lastName~.~user~
if ( user != null) {
lastNameUser = user.lastName;
}
}
// batch finished
if ((dirtyFlags & 0b11L) != 0) {
// api target 1
this.mboundView1.setText(firstNameUser);
}
if ((dirtyFlags & 0b11L) != 0) {
// api target 1
this.mboundView2.setText(lastNameUser);
}
}
在build/layout-info/debug
目录下生成的如下内容的
文件,名为:activity_data_bindingLayout.xml
文件中
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Layout layout="activity_data_binding"
modulePackage="com.banxi1988.v2exgeek"
directory="layout"
isMerge="false">
<Variables>
<entries type="com.banxi1988.v2exgeek.demo.User" name="user"/>
</Variables>
<Targets>
<Target tag="layout/activity_data_binding_0" view="LinearLayout">
<Expressions/>
</Target>
<Target tag="binding_1" view="TextView">
<Expressions>
<Expression text="user.firstName" attribute="android:text"/>
</Expressions>
</Target>
<Target tag="binding_2" view="TextView">
<Expressions>
<Expression text="user.lastName" attribute="android:text"/>
</Expressions>
</Target>
</Targets>
</Layout>
antlr
库??
操作符,方便的为null的引用设置默认值想起了 AngularJS, 以前的 JSP, 但是说绑定肯定不如AngularJS.
不过对于 Android 开发者来说,也已经是极大的进步了.
在xml的属性中写表达式, 要用到小于号大于号的都觉得挺悲剧的,希望正式版本能有更好的写法
android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}"
<variable name="userList" type="List<User>"/>