Data Binding Library数据绑定框架
来源:互联网 发布:基于比较排序算法 编辑:程序博客网 时间:2024/05/20 03:06
Data Binding Library是Google在2015年IO大会上发布的一个用于实现MVVM设计模式的支持库
环境配置
在Android Studio 2.0 原生支持Data Binding框架,配置也变得很简单,只需要在gradle中配置如下脚本即可
android { dataBinding{ enabled = true; }}
布局文件
使用Data Binding后,布局文件也跟以前的有所区别
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <import type="android.view.View"/> <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>
注意:java.lang.* 包中的类会被自动导入,可以直接使用,例如要定义一个 String 类型的变量:
<variable name="firstName" type="String" />
Includes
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:bind="http://schemas.android.com/apk/res-auto"> <data> <variable name="user" type="com.example.User"/> </data> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <include layout="@layout/name" bind:user="@{user}"/> <include layout="@layout/contact" bind:user="@{user}"/> </LinearLayout></layout>
需要注意的是,Data binding不支持include标签作为merge标签的直接子标签,例如下面的布局是不支持的
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:bind="http://schemas.android.com/apk/res-auto"> <data> <variable name="user" type="com.example.User"/> </data> <merge> <include layout="@layout/name" bind:user="@{user}"/> <include layout="@layout/contact" bind:user="@{user}"/> </merge></layout>
绑定数据
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity); User user = new User("Test", "User"); binding.setUser(user);}
- 系统会帮我们自动生成一个以xml布局文件名字开始,以Binding结束的类,例如上面的MainActivityBinding.java,另外还会生成一个BR文件,类似于R文件。
- 除了使用框架自动生成的 MainActivityBinding,我们也可以通过如下方式自定义类名
<data class="com.example.CustomBinding"></data>
use data binding items inside a ListView adapter
1、BaseAdapter
class CommonAdapter<T> extends BaseAdapter{ private List<T> mList; private Context mContext; private int layoutId; private int variableId; public CommonAdapter(List<T> list, Context context, int lauoutId, int variableId) { mList = list; mContext = context; this.layoutId = lauoutId; this.variableId = variableId; } @Override public int getCount() { return mList.size(); } @Override public Object getItem(int position) { return mList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewDataBinding binding = null; if (convertView == null){ binding = DataBindingUtil.inflate(LayoutInflater.from(mContext),layoutId,parent,false); }else { binding = DataBindingUtil.getBinding(convertView); } binding.setVariable(variableId,mList.get(position)); return binding.getRoot(); } }
2、布局文件
ListView的item布局
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="user" type="com.google.demo.model.User"/> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" app:imageUrl="@{user.icon}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.name}"/> </LinearLayout></layout>
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="adapter" type="android.widget.BaseAdapter"/> </data> <ListView android:layout_width="match_parent" android:layout_height="match_parent" app:adapter="@{adapter}"/> <!--因为ListView有setAdapter()方法,所以这里可以使用app:adapter属性--></layout>
3、逻辑代码
LayoutLvBinding binding = DataBindingUtil.setContentView(this, R.layout.layout_lv); List<User> list = new ArrayList<>(); CommonAdapter<User> adapter = new CommonAdapter<>(list,this,R.layout.lv_item, com.google .demo.BR.user); binding.setAdapter(adapter);
Observable Objects
private static class User extends BaseObservable { private String firstName; private String lastName; @Bindable public String getFirstName() { return this.firstName; } @Bindable public String getLastName() { return this.lastName; } public void setFirstName(String firstName) { this.firstName = firstName; notifyPropertyChanged(BR.firstName); } public void setLastName(String lastName) { this.lastName = lastName; notifyPropertyChanged(BR.lastName); }}
- BaseObservable:实现数据的更新同步到UI控件上需要实现该接口
- @Bindable注解标记过 的getter 方法会在 BR 中生成一个 entry
- notifyPropertyChanged(BR.firstName)通知View更新
ObservableFields
private static class User { public final ObservableField<String> firstName = new ObservableField<>(); public final ObservableField<String> lastName = new ObservableField<>(); public final ObservableInt age = new ObservableInt();}
ObservableField, ObservableBoolean, ObservableByte, ObservableChar, ObservableShort, ObservableInt, ObservableLong, ObservableFloat, ObservableDouble, and ObservableParcelable
Observable Collections
ObservableArrayMap
ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();user.put("firstName", "Google");user.put("lastName", "Inc.");user.put("age", 17);
在布局文件中使用
<data> <import type="android.databinding.ObservableMap"/> <variable name="user" type="ObservableMap<String, Object>"/></data>…<TextView android:text='@{user["lastName"]}' android:layout_width="wrap_content" android:layout_height="wrap_content"/><TextView android:text='@{String.valueOf(1 + (Integer)user["age"])}' android:layout_width="wrap_content" android:layout_height="wrap_content"/>
ObservableArrayList
ObservableArrayList<Object> user = new ObservableArrayList<>();user.add("Google");user.add("Inc.");user.add(17);
在布局文件中使用
<data> <import type="android.databinding.ObservableList"/> <import type="com.example.my.app.Fields"/> <variable name="user" type="ObservableList<Object>"/></data>…<TextView android:text='@{user[Fields.LAST_NAME]}' android:layout_width="wrap_content" android:layout_height="wrap_content"/><TextView android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}' android:layout_width="wrap_content" android:layout_height="wrap_content"/>
生成Binding class
所生成的Binding类都继承自ViewDataBinding
MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater);MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater, viewGroup, false);
MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);
ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId, parent, attachToParent);ViewDataBinding binding = DataBindingUtil.bind(viewRoot, layoutId);
绑定事件
public class MyHandlers { public void onClickFriend(View view) { ... } public void onClickEnemy(View view) { ... }}
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="handlers" type="com.example.Handlers"/> <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}" android:onClick="@{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.lastName}" android:onClick="@{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/> </LinearLayout></layout>
使用资源数据
android:padding="@{large? (int)@dimen/largePadding : (int)@dimen/smallPadding}"
Null Coalescing Operator
android:text="@{user.displayName ?? user.lastName}"
等价于
android:text="@{user.displayName != null ? user.displayName : user.lastName}"
集合的使用
<data> <import type="android.util.SparseArray"/> <import type="java.util.Map"/> <import type="java.util.List"/> <variable name="list" type="List<String>"/> <variable name="sparse" type="SparseArray<String>"/> <variable name="map" type="Map<String, String>"/> <variable name="index" type="int"/> <variable name="key" type="String"/></data>…android:text="@{list[index]}"…android:text="@{sparse[index]}"…android:text="@{map[key]}"
Custom Setters
@BindingAdapter({"imageUrl"})public static void loadImage(ImageView iv,String url){ if (url == null){ iv.setImageResource(R.mipmap.ic_launcher); }else { Glide.with(iv.getContext()).load(url).into(iv); } }
Converters(转换器)
@BindingConversionpublic static ColorDrawable convertColorToDrawable(int color) { return new ColorDrawable(color);}
<View android:background="@{isError ? @drawable/error : @color/white}" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
DataBindingComponent
所有被注解@BindingAdapter标记的方法,如果该方法为非静态方法,那么都需要一个Component对象,而所需要的Component对象由DataBindingComponent提供,所以我们需要自定义类实现DataBindingComponent接口
public class Utils { @BindingAdapter({"imageUrl"}) public static void loadImage(ImageView iv,String url){ if (url == null){ iv.setImageResource(R.mipmap.ic_launcher); }else { Glide.with(iv.getContext()).load(url).into(iv); } }}
public class MyComponent implements android.databinding.DataBindingComponent { private Utils mUtils @Override public Utils getUtils() { if (mUtils == null){ mUtils = new Utils(); } return mUtils; } }
在DataBindingUtil.setContentView()之前设置Component
DataBindingUtil.setDefaultComponent(new MyComponent());
参考
https://github.com/LyndonChin/MasteringAndroidDataBinding
- Data Binding Library数据绑定框架
- Data Binding Library(数据绑定库)
- Android数据绑定库Data Binding Library介绍
- 数据绑定数据库详解Android Data Binding Library
- Android 官方数据绑定框架 Data Binding 简单使用
- 数据绑定(Data Binding)
- 数据绑定(data binding)
- Google Data Binding Library 谷歌官方数据绑定库(二) 自定义绑定类名
- Google Data Binding Library 谷歌官方数据绑定库(六)创建的绑定类
- Data Binding Library(数据绑定库)--来自android官网的翻译
- Google Data Binding Library 谷歌官方数据绑定库(一)
- Google Data Binding Library 谷歌官方数据绑定库(四) 语法和运算符
- Google Data Binding Library 谷歌官方数据绑定库(七)属性Setter
- Google Data Binding Library 谷歌官方数据绑定库(八)转换
- Google Data Binding Library 谷歌官方数据绑定库(三)在引用布局中使用数据绑定
- HTML中的数据绑定(Data Binding)
- Android Data Binding 数据绑定技术导读
- 数据绑定(data binding )1
- 使用retainCount存在的问题
- CentOS卸载自带的Apache
- NGUI UIRoot的屏幕自适应
- Android点击View显示PopupWindow,再次重复点击View关闭PopupWindow
- ZooKeeper系列之十:ZooKeeper的一致性保证及Leader选举
- Data Binding Library数据绑定框架
- Android应用性能优化
- Struts2拦截器
- Hi3516A开发--挂载SD卡和U盘
- java HttpsURLConnection请求报错
- 2016-9-18
- Redis与memcache比较
- iOS 解决iOS10相册、相机、麦克风等权限使用问题
- 模板滤波实现(笔记)