900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > Android Data Binding Library 官方文档(译)

Android Data Binding Library 官方文档(译)

时间:2020-07-07 16:37:55

相关推荐

Android Data Binding Library 官方文档(译)

地址:https://developer./topic/libraries/data-binding/index.html

本文地址:/jjwwmlp456/article/details/54915981

Data Binding Library (数据绑定库),旨在减少绑定应用程序逻辑和布局所需的一些耦合性代码

最低支持Android 2.1 (API Level 7)

构建环境

使用gradle插件1.5-alpha1以上

在build.gradle添加如下声明

android {....dataBinding {enabled = true}}

注:如果子Moudle使用了数据绑定,那么最好也在app Moudle中配置一下

数据绑定的布局文件

书写第一组数据绑定表达式

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="/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>

如上,在<data>标签中 <variable>描述了一个变量user,它对应的类型为”com.example.User”

布局中使用“@ { }”语法来书写表达式。如为TextView的文本设置成user. firstName:

<TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{user.firstName}"/>

数据对象

a plain-old Java object (POJO) for User:

public class User {public final String firstName;public final String lastName;public User(String firstName, String lastName) {this.firstName = firstName;this.lastName = lastName;}}

也可以如下书写:

public class User {private final String firstName;private final String lastName;public User(String firstName, String lastName) {this.firstName = firstName;this.lastName = lastName;}public String getFirstName() {return this.firstName;}public String getLastName() {return this.lastName;}}

在数据绑定中,访问@{user.firstName},那么默认就会访问同名的属性firstName,或对应的getFirstName方法

绑定数据

默认情况下,绑定类将基于布局文件的名称来产生

如布局文件为main_activity.xml,这样生成的类是 MainActivityBinding

如下设置Activity的contentView:

@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.setUser(user);

还可以使用inflate的方式来获取生成数据绑定类:

MainActivityBinding binding = MainActivityBinding.inflate(getLayoutInflater());

如果是在一个adapter中来使用,那么可以如下:

ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);//orListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);

事件处理

可以在xml中编写表达式处理事件。比如 View.OnLongClickListener有一个方法为onLongClick(),那么它对应的事件就是android:onLongClick。当绑定事件后,会自动将该listener绑定在View上。处理事件有两种方法,

1. 方法引用:可以引用符合listener 任意方法签名规则的方法。

2. 监听器绑定:使用lambda表达式

方法引用

比如定义一个符合OnClickListener#onClick(View view)方法参数签名规则的方法:

public class MyHandlers {public void onClickFriend(View view) { ... }}

如下在xml中绑定并使用:

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="/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="@{handlers::onClickFriend}"/></LinearLayout></layout>

监听器绑定

表达式使用的方法就可以定义的比较随意了,不用像”方法引用”那样遵循特定规则,如一个方法

public class Presenter {public void onSaveClick(Task task){}}

使用它

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="/apk/res/android"><data><variable name="task" type="com.android.example.Task" /><variable name="presenter" type="com.android.example.Presenter" /></data><LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"><Button android:layout_width="wrap_content" android:layout_height="wrap_content"android:onClick="@{() -> presenter.onSaveClick(task)}" /></LinearLayout></layout>

注:只允许由lambda表达式作为根元素的表达式

像上面,我们并没有定义onClick(android.view.View) 参数view。监听器绑定,允许我们忽略所有的参数。如果想要使用参数,可以忽略参数类型,而随意定义一个名字。比如,上面的表达式中写上view参数:

android:onClick="@{(view) -> presenter.onSaveClick(task)}"

如果要使用该参数,可以在对应回调方法中也定义上:

public class Presenter {public void onSaveClick(View view, Task task){}}

android:onClick="@{(theView) -> presenter.onSaveClick(theView, task)}"

您可以使用一个lambda表达式,它操作多个参数:

public class Presenter {public void onCompletedChanged(Task task, boolean completed){}}

<CheckBox android:layout_width="wrap_content"android:layout_height="wrap_content"android:onCheckedChanged="@{(cb, isChecked) -> pleteChanged(task, isChecked)}" />

如果事件有返回值,那么我们定义的方法,最好也有相应的返回值。如:

public class Presenter {public boolean onLongClick(View view, Task task){}}

android:onLongClick="@{(theView) -> presenter.onLongClick(theView, task)}"

如果表达式对于null对象无法评估,那最好对应方法返回一个基本数据类型的默认值。 比如 null for reference types, 0 for int, false for boolean.

如下使用一个三元表达式:

android:onClick="@{(v) -> v.isVisible() ? doSomething() : void}"

避免复合监听

存在一些专门的单击事件处理程序,他们需要一个属性(除了android:onClick)以避免冲突:

本文地址:/jjwwmlp456/article/details/54915981

布局细节

import

在<data>标签中,import 一些class,就像在java 代码中一样

<data><import type="android.view.View"/></data>

在layout布局中使用:

<TextViewandroid:text="@{user.lastName}"android:layout_width="wrap_content"android:layout_height="wrap_content"android:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/>

当有类名称冲突,其中一个类可以重命名一个别名:

<import type="android.view.View"/><import type="com.example.real.estate.View"alias="Vista"/>

在<variable>标签来使用import中的类型:

<data><import type="com.example.User"/><import type="java.util.List"/><variable name="user" type="User"/><variable name="userList" type="List&lt;User&gt;"/></data>

<TextView android:text="@{((User)(user.connection)).lastName}"android:layout_width="wrap_content"android:layout_height="wrap_content"/>

也可以在表达式中运用静态属性或方法,使用MyStringUtils.capitalize():

<data><import type="com.example.MyStringUtils"/><variable name="user" type="com.example.User"/></data>…<TextViewandroid:text="@{MyStringUtils.capitalize(user.lastName)}"android:layout_width="wrap_content"android:layout_height="wrap_content"/>

像java代码中一样,也会自动引入java.lang.*

Variable

可以定义多个<variable>标签

<data><import type="android.graphics.drawable.Drawable"/><variable name="user" type="com.example.User"/><variable name="image" type="Drawable"/><variable name="note" type="String"/></data>

这些variable变量在编译时会进行类型检查,如果一个variable实现了Observable接口或是一个Observable的collection,那就需要在type中声明;如果不是一个Observable的实现,那么该variable就不会被观察到

不同的配置有不同的布局文件(如横屏或竖屏),在这些布局文件之间,不能定义相互冲突的变量。

自动生成的绑定类,对每个variable,都会生成 setter和getter方法。在setter方法被调用前,它会有一个默认值,比如 空引用类型null、int类型0、boolean类型false

一个特定的变量context在表达式需要时,会被生成。这个context值为根view的getContext()值。

自定义绑定 class names

默认情况下,基于布局文件的名称而生成绑定类,开头大写,然后移除下划线,再加上后缀”Binding”。这个类将被放置在一个数据绑定包中,该包位于moudle包下。例如, 布局文件contact_item.xml将生成ContactItemBinding。如果moudle的包名为com.example.my.app, 那么它将被放置在com.example.my.app.databinding下

通过调整data元素的class属性,绑定类可以重命名或放置在不同的包。例如:

<data class="ContactItem">...</data>

这会生成在moudle下的databinding包下,如果要生成moudle包下,可以使用”.”前缀:

<data class=".ContactItem">...</data>

在下面这种情况下,ContactItem直接生成在模块包下。可以使用任何完整的包路径:

<data class="com.example.ContactItem">...</data>

include

variables可以传递给使用了include标签的子布局中,如

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="/apk/res/android"xmlns:bind="/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>

如上,在name.xml和contract.xml中都可以使用变量user了

不支持在merge下直接使用include的情形,如下:

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="/apk/res/android"xmlns:bind="/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>

表达式语言

共同的特征

表达式语言看起来很像Java表达式。如下这些都是相同的:

Mathematical + - / * %String concatenation +Logical && ||Binary & | ^Unary + - ! ~Shift >> >>> <<Comparison == > < >= <=instanceofGrouping ()Literals - character, String, numeric, nullCastMethod callsField accessArray access []Ternary operator ?:

例:

android:text="@{String.valueOf(index + 1)}"android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}"android:transitionName='@{"image_" + id}'

丢失的操作符

this、new、super 如这些,还是只能在java类中使用

合并null操作符

如下使用 “??” 操作符

android:text="@{user.displayName ?? user.lastName}"

等价于:

android:text="@{user.displayName != null ? user.displayName : user.lastName}"

属性引用

如下,user有getLastName(),可以简单引用:

android:text="@{user.lastName}"

避免NullPointerException

数据绑定代码会自动检查null值,避免NullPointerException。像上文说过,会给定一个默认值

集合

一般的集合都可以使用”[]”操作符: arrays, lists, sparse lists, and maps。例

<data><import type="android.util.SparseArray"/><import type="java.util.Map"/><import type="java.util.List"/><variable name="list" type="List&lt;String&gt;"/><variable name="sparse" type="SparseArray&lt;String&gt;"/><variable name="map" type="Map&lt;String, String&gt;"/><variable name="index" type="int"/><variable name="key" type="String"/></data>…android:text="@{list[index]}"…android:text="@{sparse[index]}"…android:text="@{map[key]}"

字符串字面值

如下,可以使用单引号在属性值上,用双引号在字符串字面值上:

android:text='@{map["firstName"]}'

也可以反过来使用:

android:text="@{map[`firstName`}"android:text="@{map['firstName']}"

资源

可以使用正常的访问资源的表达式语法:

android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"

可以为格式字符串和复数提供参数:

android:text="@{@string/nameFormat(firstName, lastName)}"android:text="@{@plurals/banana(bananaCount)}"

当一个复数多个参数,:

Have an orangeHave %d orangesandroid:text="@{@plurals/orange(orangeCount, orangeCount)}"

一些资源需要显式类型的评估:

本文地址:/jjwwmlp456/article/details/54915981

数据对象

任何POJO对象都可以用于数据绑定,但是更改POJO对象,并不会引起UI更新。有三种不同的数据更改通知机制:观察对象,观察字段和观察集合。当其中一个绑定到用户界面的可观察的数据对象,观察到数据对象的属性变化,用户界面将自动更新。

观察对象(Observable Objects)

A class implementing the Observable interface ,将被允许附加一个listener,来监听对象所有属性的改变

Observable interface有一个机制来添加和删除listeners,但需要通知开发者。为了让开发变得更容易,提供一个基类,BaseObservable,它实现创建listener的注册机制。当属性数据改变时,数据类实现者需要响应通知。这是通过在getter上使用一个注解@Bindable,并在setter中进行通知。

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);}}

@Bindable 在编译时将生成一个BR class 。BR类文件将生成在moudle的package下。如果数据类的基类不能被改变,Observable interface的实现类可以使用PropertyChangeRegistry存储和有效地通知listeners。

观察属性(ObservableFields)

如果想做比创建上面的观察对象更少的工作,那么可以使用ObservableField 和它的同级的一些类型: ObservableBoolean, ObservableByte, ObservableChar, ObservableShort, ObservableInt, ObservableLong, ObservableFloat, ObservableDouble, and ObservableParcelable。它们都是一个包含单一属性的可观察的对象。为避免装箱、拆箱操作,可以在数据类中定义成 public final field …

private static class User {public final ObservableField<String> firstName =new ObservableField<>();public final ObservableField<String> lastName =new ObservableField<>();public final ObservableInt age = new ObservableInt();}

如下,使用get或set来获取和设置属性值:

user.firstName.set("Google");int age = user.age.get();

观察集合(Observable Collections)

一些应用程序使用更多的动态结构来保存数据。可观察集合允许通过key访问这些数据对象。当key是一个引用类型,如String,就可以用ObservableArrayMap。

ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();user.put("firstName", "Google");user.put("lastName", "Inc.");user.put("age", 17);

在下面的布局中,就可以通过String类型的key来访问map中的数据:

<data><import type="android.databinding.ObservableMap"/><variable name="user" type="ObservableMap&lt;String, Object&gt;"/></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"/>

当key是一个Integer时,可用ObservableArrayList:

ObservableArrayList<Object> user = new ObservableArrayList<>();user.add("Google");user.add("Inc.");user.add(17);

布局中使用ObservableArrayList:

<data><import type="android.databinding.ObservableList"/><import type="com.example.my.app.Fields"/><variable name="user" type="ObservableList&lt;Object&gt;"/></data>…<TextViewandroid:text='@{user[Fields.LAST_NAME]}'android:layout_width="wrap_content"android:layout_height="wrap_content"/><TextViewandroid:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}'android:layout_width="wrap_content"android:layout_height="wrap_content"/>

本文地址:/jjwwmlp456/article/details/54915981

生成Binding

生成的绑定类,会链接布局的variables。正如前面所讨论的,绑定的名称和包可能是自定义的的。生成的所有绑定类都 extends ViewDataBinding。

创建

如前文所述,由相应的布局文件,而生成了相应的binding class。代码中使用它,需要LayoutInflater,如:

MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater);MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater, viewGroup, false);

如果布局已经inflate了,在某些场景时,可以单独绑定:

MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);

有时binding class 不能提前知道。在这种情况下,可以使用DataBindingUtil类创建绑定:

ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId, parent, attachToParent);ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId);

View中使用id

在布局中的每个使用了id的view,都会在binding class中创建出一个同名的public属性。这种绑定机制,比findViewById更快速。例:

<layout xmlns:android="/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}"android:id="@+id/firstName"/><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{user.lastName}"android:id="@+id/lastName"/></LinearLayout></layout>

在binding class中将会生成:

public final TextView firstName;public final TextView lastName;

不使用data binding的view,可以没有id,但有些view还是需要在代码中来访问

Variable

将为每个variable生成getter和setter方法。如

<data><import type="android.graphics.drawable.Drawable"/><variable name="user" type="com.example.User"/><variable name="image" type="Drawable"/><variable name="note" type="String"/></data>

上面的代码将生成:

public abstract com.example.User getUser();public abstract void setUser(com.example.User user);public abstract Drawable getImage();public abstract void setImage(Drawable image);public abstract String getNote();public abstract void setNote(String note);

ViewStub

ViewStub 这种view与普通的view有一点不同。它的特点是,在一开始,它是不可见的;在需要可见时,会由配置的另一个布局来替换自身简单的说,如果要使用数据绑定,那么在ViewStub所配置的布局inflate之前,该布局就已建立好了data binding

高级绑定

动态Variable

有时,特定的绑定类不会为人所知。例如,一个RecyclerView.Adapter操作的任意布局,不知其特定的绑定类。仍需要通过onBindViewHolder(VH, int)来绑定值。

在下面的例子中,RecyclerView中的所有布局,都绑定了一个”item”,有一个BindingHolder#getBinding() 返回ViewDataBinding 类型:

public void onBindViewHolder(BindingHolder holder, int position) {final T item = mItems.get(position);holder.getBinding().setVariable(BR.item, item);holder.getBinding().executePendingBindings();}

直接绑定

当一个variable or observable发生了改变,绑定框架会安排在下一帧进行视图的改变。然而,有时希望立即发生改变。可以使用executePendingBindings()来强制执行

后台线程

你可以改变你的数据模型在一个后台线程,只要它不是一个集合。数据绑定框架将本地化每个变量和属性,以避免任何并发问题。

Attribute Setters

当view使用了绑定表达式,只要绑定值发生变化,生成的绑定类必须调用相应的setter方法。定制数据绑定框架的方式方法调用设置值。数据绑定框架允许自定义setter方法。

自动Setters

对于一个attribute,数据绑定框架将试图查找对应的setAttribute()。它的namespace并不重要,只关注attribute的name。如,TextView中的属性android:text使用了表达式,那么框架就会查找setText(String)。如果表达式返回的是int,那么将会查找setText(int)。所以,表达式需要返回正确的类型。数据绑定框架,支持创建一个布局元素(View|ViewGroup)中,并不存在的属性。

如下,生成的binding class中,将生成一个setDrawerListener(listener):

<android.support.v4.widget.DrawerLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"app:scrimColor="@{@color/scrim}"app:drawerListener="@{fragment.drawerListener}"/>

重命名 Setters

有一些属性的setter方法,与它的属性名不匹配。这些属性的setter可能会通过使用@BindingMethods,来进行重命名。要求内问包含@BindingMethod。例如ImageView有一个属性android:tint,它对应setter方法为setImageTintList(ColorStateList tint):

@BindingMethods({@BindingMethod(type = "android.widget.ImageView",attribute = "android:tint",method = "setImageTintList"),})

开发人员将不太可能需要重命名setter,因android属性框架已经实现。

自定义Setters

一些属性需要自定义绑定逻辑。例如,属性android:paddingLeft没有对应的setter方法,而在view中有一个方法为setPadding(left, top, right, bottom)。可以使用@BindingAdapter来自定义一个关于属性android:paddingLeft的setter。例:

@BindingAdapter("android:paddingLeft")public static void setPaddingLeft(View view, int padding) {view.setPadding(padding,view.getPaddingTop(),view.getPaddingRight(),view.getPaddingBottom());}

@BindingAdapter也可以运用在自定义类型上。 当数据绑定框架创建的Binding adapter

与开发人员创建的有冲突时,会采用开发人员所创建的来替代。

还可以用Binding adapter来接收多个参数:

@BindingAdapter({"bind:imageUrl", "bind:error"})public static void loadImage(ImageView view, String url, Drawable error) {Picasso.with(view.getContext()).load(url).error(error).into(view);}

对应的xml绑定:

<ImageView app:imageUrl="@{venue.imageUrl}"app:error="@{@drawable/venueError}"/>

当ImageView中同时使用了属性String imageUrl和Drawlable error,通过Binding adapter,这时的setter就是 loadImage()

注意:在匹配时,自定义namespace将被忽略。在编写Binding adapter时,也可以使用android的namespace

下面的示例,表示默认采用oldPadding值,如果与newPadding不一致,则用newPadding:

@BindingAdapter("android:paddingLeft")public static void setPaddingLeft(View view, int oldPadding, int newPadding) {if (oldPadding != newPadding) {view.setPadding(newPadding,view.getPaddingTop(),view.getPaddingRight(),view.getPaddingBottom());}}

事件处理绑定表达式,对应的Binding Adapter只能使用接口或有一个抽象方法的抽象类。例如:

@BindingAdapter("android:onLayoutChange")public static void setOnLayoutChangeListener(View view, View.OnLayoutChangeListener oldValue,View.OnLayoutChangeListener newValue) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {if (oldValue != null) {view.removeOnLayoutChangeListener(oldValue);}if (newValue != null) {view.addOnLayoutChangeListener(newValue);}}}

当一个listener有多个方法,它必须拆分成多个listener。例如,在View中,OnAttachStateChangeListener有两个方法:onViewAttachedToWindow()和onViewDetachedFromWindow()。我们必须创建两个接口来区分的属性和事件处理。

@TargetApi(VERSION_CODES.HONEYCOMB_MR1)public interface OnViewDetachedFromWindow {void onViewDetachedFromWindow(View v);}@TargetApi(VERSION_CODES.HONEYCOMB_MR1)public interface OnViewAttachedToWindow {void onViewAttachedToWindow(View v);}

为此,我们就需要创建三个Binding Adapter:

@BindingAdapter("android:onViewAttachedToWindow")public static void setListener(View view, OnViewAttachedToWindow attached) {setListener(view, null, attached);}@BindingAdapter("android:onViewDetachedFromWindow")public static void setListener(View view, OnViewDetachedFromWindow detached) {setListener(view, detached, null);}@BindingAdapter({"android:onViewDetachedFromWindow", "android:onViewAttachedToWindow"})public static void setListener(View view, final OnViewDetachedFromWindow detach,final OnViewAttachedToWindow attach) {if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) {final OnAttachStateChangeListener newListener;if (detach == null && attach == null) {newListener = null;} else {newListener = new OnAttachStateChangeListener() {@Overridepublic void onViewAttachedToWindow(View v) {if (attach != null) {attach.onViewAttachedToWindow(v);}}@Overridepublic void onViewDetachedFromWindow(View v) {if (detach != null) {detach.onViewDetachedFromWindow(v);}}};}final OnAttachStateChangeListener oldListener = ListenerUtil.trackListener(view,newListener, R.id.onAttachStateChangeListener);if (oldListener != null) {view.removeOnAttachStateChangeListener(oldListener);}if (newListener != null) {view.addOnAttachStateChangeListener(newListener);}}}

上面的例子,表示三种情形:1. 只需要监听Attached..;2. 只需要监听Detached..;3:同时监听前面两种。

第三个例子中,同时适配Attached和Detached,代码的最后通过android.databinding.adapters.ListenerUtil来查找view上是否已经绑定过OnAttachStateChangeListener

在接口定时,使用了@TargetApi(VERSION_CODES.HONEYCOMB_MR1),让数据绑定框架知道,只在系统为Honeycomb MR1(api level 12)或更高时,才支持addOnAttachStateChangeListener(View.OnAttachStateChangeListener).

本文地址:/jjwwmlp456/article/details/54915981

转换器

对象转换

当从一个绑定表达式返回一个对象,就会有一个setter被采用。该对象将会被转换成setter中的参数类型。

下面的例子,通过ObservableMaps来保存数据:

<TextView android:text='@{userMap["lastName"]}'android:layout_width="wrap_content"android:layout_height="wrap_content"/>

userMap返回一个对象,该对象将自动转换成setText(CharSequence)中的参数类型。可能会有混乱的参数类型,开发人员需要在表达式中显式cast

自定义转换

有时特定类型之间会自动转换。例如,设置背景:

<Viewandroid:background="@{isError ? @color/red : @color/white}"android:layout_width="wrap_content"android:layout_height="wrap_content"/>

这里,background的setter的参数类型应该是一个drawable,但color是一个整数。应当有一个转换规则,将int color转换为ColorDrawable。这种转换是通过使用一个@BindingConversion的静态方法来实现的:

@BindingConversionpublic static ColorDrawable convertColorToDrawable(int color) {return new ColorDrawable(color);}

注意,转换只发生在setter时期。所以不允许混合类型,如:

<Viewandroid:background="@{isError ? @drawable/error : @color/white}"android:layout_width="wrap_content"android:layout_height="wrap_content"/>

本文地址:/jjwwmlp456/article/details/54915981

Android Studio Support for Data Binding

Studio支持许多数据绑定代码的编辑功能。例如,它支持数据绑定表达式的以下特点:

语法高亮表达式语言的语法错误提示XML 代码实现参考,包括导航(如导航到某一项的声明)和快速查阅文档

注意:Arrays和泛型类型,比如一个可观察class,可能没有错误,但studio提示有错

在预览xml时,如果有为属性配置默认值,就能显示。如下的例子,使用default关键字设置了默认text为PLACEHOLDER,所以在预览时就能看到它的默认文本为PLACEHOLDER。

<TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{user.firstName, default=PLACEHOLDER}"/>

如果需要在程序设计阶段,显示默认值,那么最好还是不要用default绑定表达式。比如在不采用Data Binding时,就无法使用default绑定表达式了。可以采用tools属性。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。