Android DataBinding 高级用法

DataBinding快速上手,布局细节:
1.< data>…< /data>标签内可以有多个 import 标签。你可以在布局文件中像使用 Java 一样导入引用。

2.当类名发生冲突时,可以使用 alias,像这样:

< data>

<import type=“com.wenzhibin.View”

alias=“myView”/>

< /data>

3.< data>…< /data>标签内可以有任意数量的 variable 标签。每个 variable 标签描述了会在 binding 表达式中使用的属性。每个variable 标签里的name值就是 binding 类中的一个变量。

4.自动生成的 binding 类为每一个变量生成 getter/setter 函数。这些变量会使用 Java 的默认赋值,直到 setter 函数被调用。默认赋值有 null,0(int),false(boolean)等。如下例子:

在XML中,

< data>

< import type=“android.graphics.drawable.Drawable”/>

< variable name=“studentModel” type=“com.wenzhibin.StudentModel”/>

< variable name=“image” type=“Drawable”/>

< variable name=“note” type=“String”/>

< /data>

自动生成的 binding 类中生成对应的 getter setter,

public abstract com.wenzhibin.StudentModel.getStudentModel();

public abstract void setStudentModel(com.wenzhibin.StudentModel studentModel);

public abstract Drawable getImage();

public abstract void setImage(Drawable image);

public abstract String getNote();

public abstract void setNote(String note);

5.当针对不同配置编写不同的布局文件时(比如横屏竖屏的布局),变量会被合并。所以这些不同配置的布局文件之间不能存在冲突。

6.导入也可以用于在表达式中使用静态方法,

例如:

public class StringUtils{

public static Stringnew(final String word){

if(word.length() >5) {

return word+“正在学习DataBinding的高级用法”;

}

return word;

}

}

< data>
< import type=“com.wenzhibin.utils.StringUtils” />
< variable name=“studentModel” type=“com.wenzhibin.StudentModel”/>

< /data>

<TextView

android:text="@{StringUtils.Stringnew(studentModel.name)}"

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”/>

7.java.lang.* 包中的类会被自动导入,可以直接使用,例如, 要定义一个 String 类型的变量:

**

DataBinding高级用法:

**
**

1.列表绑定

**

RecyclerView数据绑定开源库:

evant / binding-collection-adapter

radzio / android-data-binding-recyclerview

如果觉得这两库不够灵活,可以自己封装。

2.自定义属性

绑定的时候,会调用 setXXX 方法,如果这个view提供该属性方法就可以通过 DataBinding 来设置,比如TextView 本身就内置了 setText(String text) 方法,只需要我们android:text="@{studentModel.name}",DataBinding就会自动寻找set方法------>setText(studentModel.namet) 上去,假设TextView没有 setText(String text)这个方法,这时就需要自定义属性了。有两种写法:

a)如果有类似的方法,方法名不一样,可以通过设置 BindingMethod来调用现有的方法。

比如 android:onClick,View 中没有 setOnClick 方法,但是有 setOnClickListener 方法,

这时候我们可以使用 BindingMethod(又称为Binding方法) 来做个映射。当在xml文件中看到"android:onClick"使用了DataBinding时,会把setOnClick映射到setOnClickListener上

@BindingMethods({

@BindingMethod(

type=View.class,

attribute=“android:onClick”,

method=“setOnClickListener”)

})

@BindingMethods 定义到类名上面。(ps:就是在某一个class类的前面加上上面这段代码,编译前会检查这个注释,然后作为一个Binding方法,自动调用)

当然,如果仅仅只是想重命名 setter方法,也可以通过 @BindingMethods 来实现。

b). 如果没有类似方法,可以通过设置BindingAdapter添加对应的方法。

比如 android:paddingRighttts,View 中是没有 setPaddingpaddingRighttts 方法的,只有 setPadding 方法。

这时候可以自定义一个 set 方法,并在方法上面添加 @BindingAdapter(又称为Binding适配器)。

//单个属性

@BindingAdapter(“android:paddingRighttts”)

public static void setPaddingRightRighttts(View view, int padding){

view.setPadding( view.getPaddingLeft(), view.getPaddingTop() ,padding, view.getPaddingBottom());

}

//多属性适配,同一个方法,可以同时设置多个属性

public class MyBindingAdapter {

@BindingAdapter({“imageUrl”,“placeholder”})

public static void loadImageFromUrl(ImageView view,String url,Drawable drawable) {

Glide.with(view.getContext()).load(url).placeholder(drawable).into(view);

}

}

在xml中使用,(MyBindingAdapter这个类的Binding适配器会自动调用)

< data>
< import type=“android.graphics.drawable.Drawable”/>
< variable name=“studentModel” type=“com.wenzhibin.StudentModel”/>

< /data>

<ImageView

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:scaleType=“fitXY”

app:imageUrl="@{studentModel.headUri}"

app:placeholder="@{@drawable/default_headimg}"/>

(**ps:**如果这样写@BindingAdapter({“xxx”})或者是这样写@BindingAdapter({“bind:xxx”}),xml布局引用属性时这样写app:xxx="@{…}";如果这样写@BindingAdapter({“android:xxx”}),xml布局引用属性时这样写android:xxx="@{…}")

**

3.BindingConversion转换为setter需要的属性

**

<View

android:background= “@(isError ? @color/red : @color/white}”

android:layout_width= “wrap_content”

android:layout_height= “wrap_content” />

@BindingConversion

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

代码示例中,View的background属性需要的是Drawable,但是我们赋了color给它,通过 @BindingConversion 可以把color转换为Drawable,就可以使用color做background背景了。

4.双向绑定

一方面Model的变化会影响到UI界面的显示;另一方面UI界面的变化也会影响Model中对应字段的更新,简单来讲就是彼此相互影响,这就是双向绑定。在XML中使用”@=“就可以轻松实现双向绑定了。比如:

在XML中示例代码:

< data>

<variable

name=“studentModel”

type=“com.wenzhibin.StudentModel”/>

< /data>

<EditText

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:inputType=“textNoSuggestions”

android:text="@={studentModel.name}"/>

<Button

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:text="@{studentModel.name}"/>

当用户输入时,上的text会发生变化,text会直接赋给StudentModel的name属性,此时Button的text和的text显示相同内容,因为StudentModel已经更新了。我们还可以监听属性变更,在java代码中如下示例:

studentModel.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
@Override

public void onPropertyChanged(Observable observable,int i) {

……

do something
……

}

5.表达式链

在XML出现重复的表达式:

< data>

< import type=“android.view.View”/>

< /data>

< ImageView android:visibility= “@{studentModel.isGraduate ? View.VISIBLE : View.GONE}” />

< TextView android:visibility= “@{studentModel.isGraduate ? View.VISIBLE : View.GONE}” />

< CheckBox android:visibility= “@{studentModel.isGraduate ? View.VISIBLE : View.GONE}” />

通过简化后的表达式:

< data>

< import type=“android.view.View”/>

< /data>

<ImageView

android:id= “@+id/img_head”

android:visibility= “@{studentModel.isGraduate ? View.VISIBLE : View.GONE}” />

< TextView android:visibility= “@{img_head.visibility}” />

< CheckBox android:visibility="@{img_head.visibility}"/>

隐式更新

< data>

< import type=“android.view.View”/>

< /data>

< CheckBox android:id= “@+id/isRemember” />

< ImageView android:visibility= “@{isRemember.checked? View.VISIBLE : View.GONE}” />

如上示例可以看出,我们不需要再去Java代码中判断CheckBox是否被选中,来控制图片的显示与隐藏。

6.lambda表达式

a)方法引用的替代者

android:onClick ="@ {(view)-> presenter.onUserClick(view,user)}”

b)省略参数,或申明所有参数(通常不需要view)

android:onClick ="@ {()-> presenter.onUserClick(user)}"

android:onFocusChange =“@{(v,fcs)-> presenter.onFocusChangelistner(user)}"

c)Lambda中可以使用表达式,引用变量

d)特殊变量:view id(传另一个View的驼峰变量名),包括context变量

示例代码:

在LambdaDemoActivity类中
public class LambdaDemoActivity extends AppCompatActivity {

private ActivityLambdaDemoBinding myBinding;

public class Presenter {

onUserClick(User user) {

Toast.makeText(LambdaDemoActivity.this,“onUserClick”,

Toast.LENGTH_SHORT).show();

}

public void onUserLongClick(User user, Context mContext) {

Toast.makeText(mContext,“onUserLongClick”,

Toast.LENGTH_SHORT).show();

}

public void onFocusChangelistner(User user) {

Toast.makeText(LambdaDemoActivity.this,“onFocusChangelistner”,

Toast.LENGTH_SHORT).show();

}

}

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myBinding = DataBindingUtil.setContentView(this, R.layout.activity_lambda_demo);
myBinding.setUser(new User(“wenzhibin”,“123456”));
myBinding.setPresenter(new Presenter());

}

}

在activity_lambda_demo.xml中

< data>

< variable name=“presenter” type=“com.wenzhibin.LambdaDemoActivity.Presenter”/>

< variable name=“user” type=“com.wenzhibin.User”/>

< /data>

<Button android:onClick ="@ {()-> presenter.onUserClick(user)}"/>

(**ps:**下面这行代码是申明所有参数,这两个参数名可以随便写,可以不是v、fcs,只要两参数名不同就行。甚至省略所有参数,下面v、fcs这两个参数不写也是可以的。)
<Button android:onFocusChange =“@{(v,fcs)-> presenter.onFocusChangelistner(user)}"/>

<Button
android:text="@{user.loginName}"

(**ps:**在XML布局中我们并没有定义context这个变量,是databinding内部帮我们拿到了context,即拿到了这个activity)
android:onClick="@{(v) -> presenter.onUserLongClick(user, context)

}/>

7.动画

databinding已经封装了动画,我们只需要调用如下代码即可:

myBinding.addOnRebindCallback(new OnRebindCallback() {

@SuppressLint(“NewApi”)
@Override
public boolean onPreBind(ViewDataBinding binding) {

ViewGroup view = (ViewGroup) binding.getRoot();

TransitionManager.beginDelayedTransition(view);

return true;

}

});

猜你喜欢

转载自blog.csdn.net/yanhuomatou2015/article/details/108840947