Data Binding Library数据绑定框架
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>
标签 | 说明 |
---|---|
layout | 布局文件的根节点 |
data | 要实现 MVVM 的 ViewModel 就需要把数据(Model)与 UI(View) 进行绑定,data 节点的作用就像一个桥梁,搭建了 View 和 Model 之间的通路 |
variable | 声明变量 |
import | 导包 |
@{ } | 使用定义的变量 |
注意: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>
绑定数据
@Override
protected 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;}@Overridepublic int getCount() {return mList.size();}@Overridepublic Object getItem(int position) {return mList.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic 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;@Bindablepublic String getFirstName() {return this.firstName;}@Bindablepublic 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(转换器)
@BindingConversion
public 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@Overridepublic 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
本文翻译自文章:Data Binding Library 翻译人员:麦田里的守望者-Lost 例子下载地址:DataBinding-Example 这篇文章介绍了如何使用Data Binding Li ...
- Android Data Binding Library 官方文档(译)
地址:https://developer.android.google.cn/topic/libraries/data-binding/index.html 本文地址:http://blog.csdn ...
- Android官方数据绑定框架DataBinding(一)
还记得在博客<高逼格UI-ASD(Android Support Design)>的开始曾经说过,Android最新推出了一个官方的数据绑定框架-Data Binding Library. ...
- WPF中的数据绑定Data Binding使用小结
完整的数据绑定的语法说明可以在这里查看: http://www.nbdtech.com/Free/WpfBinding.pdf MSDN资料: Data Binding: Part 1 http:// ...
- XAML数据绑定(Data Binding)
XAML数据绑定(Data Binding) Data Binding可以使得XAML标签属性的赋值更为灵活和方便.在绑定过程中,获取数据的标签成为目标标签:提供数据的标签成为源标签.在XAML中,一 ...
- Android数据绑定框架DataBinding用法
Android数据绑定框架DataBinding用法 [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/details/5195374 ...
- Android开发之关于MVVM架构中视图数据绑定框架dataBinding的基本用法
dataBinding是Google官方开发的第三方视图数据绑定框架.优缺点如下: 优点:很好用 缺点:调试bug不易,部分AS版本中不太友好 首先说下如何使用: 在gradle中的android模块 ...
- Android Data Binding 详细介绍与使用
构建环境 首先,确保能使用Data Binding,需要下载最新的 Support repository.否则可能报错,如图: 在模块的build.gradle文件中添加dataBinding配置 a ...
- Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion
本篇太乱,请移步: Spring Framework 官方文档学习(四)之Validation.Data Binding.Type Conversion(一) 写了删删了写,反复几次,对自己的描述很不 ...
最新文章
- eclipse提示jre_给新手 Java 开发者的 7 点提示 | Linux 中国
- 2019年安徽省模块七满分多少_二级造价考情分析:20年二级造价考试还有戏吗?...
- mysql5.6.37驱动_MySql (mysql-5.6.37) 在Windows的安装及使用
- 【转帖】dopod touch diamond 应用小常识:)
- xml 数字签名 破解_JAVA中带有数字签名的XML安全性
- [转载] Java中Array(数组)转List(集合类)的几种方法
- 爬虫-获取访问后可见的页面-get方法cookies参数形式
- 霸气!Power 支持混合云、多云,性能完胜 x86!
- 利用数组求前n个质数
- 鸿蒙OpenHarmony hi3516开发板,标准系统实现智能门禁
- Linux 2038年问题
- 英文数据集txt_【美股量化07篇】Python获取标普500成分股数据
- Latex 摘要部分
- 使用ffmpeg合并多个视频文件
- python 点点滴滴
- 小米世界第三,华为首次跌出前五
- 总结numpy中的ndarray,非常齐全
- DELL-R730服务器U盘安装操作系统指南
- 蜂巢贷:车抵贷款和房屋抵押贷款的区别
- 游戏角色ai的实现方式讨论
热门文章
- 3月第3周新闻回顾:3Com案三日动荡 珊瑚虫作者入狱3年
- SD-WAN技术分析—Vecloud
- 搞不懂SDN和SD-WAN?那是因为你没看这个小故事—Vecloud微云
- Android Studio上手,基于VideoView的本地文件及流媒体播放器
- 第八章 Python类中常用的特殊变量和方法
- 2019.4.1考试2019.4.2考试2019.4.4考试
- 力扣——所有可能的满二叉树
- django模板中使用JQ代码实现瀑布流显示效果
- 为什么使用消息队列? 消息队列有什么优点和缺点? Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别,以及适合哪些场景?...
- 使用Apache Archiva管理Maven仓库