
用于 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>"/>