(jetPack)数据绑定(一)

数据绑定库

一、搭建环境

build.grage 添加 dataBinding

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

二、示例项目:

xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="user1"
            type="union.com.viewgroup.jetpack.User" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

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

    </LinearLayout>

</layout>

activity 代码:

package union.com.viewgroup.jetpack;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;

import android.os.Bundle;

import union.com.viewgroup.R;
import union.com.viewgroup.databinding.ActivityDataBindingBinding;

public class MyActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityDataBindingBinding binding = DataBindingUtil.setContentView(MyActivity.this, R.layout.activity_data_binding);
        binding.setUser1(new User("张","三"));
     }
}

在运行时,您可以使用 LayoutInflater 来获取视图 代码如下:

 ActivityDataBindingBinding activityMainBinding =  ActivityDataBindingBinding.inflate(getLayoutInflater());

如果你想使用数据绑定绑定Fragment ,ListView 或者 RecyclerView adapter 你可以使用inflate 方法 来绑定类名,代码如下:

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

三、表达式

1、+ - / * %

2、 字符串拼接 +

3、 逻辑运算符 && ||

4、二进制云运算符 & | ^

5、 单目运算符 + - ! ~

6、移位运算符 >> >>> <<

7、比较运算符 == > < >= <= 注意 < 需要转换为 &lt

8、 instanceof

9、分组

10、文字字符 ,字符串 、数字 、null

11、Cast

12 、字段

13、数组

14、?:

example:

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

四、不支持的操作

this、 super、 new 、显示泛型调用

空合并运算符

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

在功能上等效于:

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

五、避免空指针

生成的数据绑定代码自动检查null值,并避免空指针异常。例如,在表达式中@{user.name},如果 user为null,user.name则为其指定默认值null。如果您引用的user.age是age类型int,则数据绑定使用默认值0

六、集合

<data>
	<import type = "android.util.SparseArray" />
	<import type = "java.util.Map" />
	<import type = "java.util.List" />
	<variable name="list" type="List&lt;String>"/>
    <variable name="sparse" type="SparseArray&lt;String>"/>
    <variable name="map" type="Map&lt;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]}"

**注意:**为了使XML在语法上正确,必须对<字符进行转义 。例如:List<String>List&lt;String>

您也可以使用object.key符号在地图中引用值。例如,@{map[key]}在上面的示例中,可以将替换为 @{map.key}

七、字符串文字

您可以使用单引号将属性值引起来,这允许您在表达式中使用双引号,如以下示例所示:

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

也可以使用双引号将属性值引起来。这样做时,字符串文字应该用反引号引起来```:

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

八、资源

您可以使用一下语法访问表达式中的资源

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

格式字符串和复数形式可以通过提供参数来评估:

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

当复数带有多个参数时,应传递所有参数:

  Have an orange
  Have %d oranges

android:text="@{@plurals/orange(orangeCount, orangeCount)}"

某些资源需要显式类型评估,如下表所示:

类型正常参考表达式参考
String[]@array@stringArray
int[]@array@intArray
TypedArray@array@typedArray
Animator@animator@animator
StateListAnimator@animator@stateListAnimator
color int@color@color
ColorStateList@color@colorStateList

九、事件处理

数据绑定允许你写一个表达式来捕获时间 例如 onClick 方法

属性和 事件对应如下:

ClassListener setterAttribute
SearchViewsetOnSearchClickListener(View.OnClickListener)android:onSearchClick
ZoomControlssetOnZoomInClickListener(View.OnClickListener)android:onZoomIn
ZoomControlssetOnZoomOutClickListener(View.onClickListener)android:onZoomOut

您可以使用以下机制来处理事件:

方法引用:

在表达式中,您可以引用符合侦听器方法签名的方法。当表达式对方法引用求值时,数据绑定将方法引用和所有者对象包装在侦听器中,然后在目标视图上设置该侦听器。如果表达式的计算结果为null,则数据绑定不会创建侦听器,null而是会设置侦听器。

帧听器绑定:

这是事件发生时评估的lambda表达式。数据绑定始终创建一个侦听器,并在视图上进行设置。调度事件后,侦听器将评估lambda表达式。

方法引用和侦听器绑定之间的主要区别在于,实际的侦听器实现是在绑定数据时创建的,而不是在事件触发时创建的。如果您希望在事件发生时评估表达式,则应使用监听器绑定

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

xml 定义如下:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="handlers" type="com.example.MyHandlers"/>
       <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>

**注意:**表达式中方法的签名必须与侦听器对象中方法的签名完全匹配。

帧听器绑定:

帧听器绑定是事件发生时运行的绑定表达式。它们类似于方法引用,但是它们使您可以运行任意数据绑定表达式。适用于Gradle 2.0版及更高版本的Android Gradle插件提供了此功能

在方法引用中,方法的参数必须与事件侦听器的参数匹配。在侦听器绑定中,只有您的返回值必须与侦听器的期望返回值匹配(除非期望返回void)。

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

xml:

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

在表达式中使用回调时,数据绑定将自动创建必要的侦听器并将其注册为事件。当视图触发事件时,数据绑定将评估给定的表达式。像在常规表达式中一样,在评估这些侦听表达式时,您仍然可以获得数据绑定的null 和线程安全

在上面的示例中,我们尚未定义view 传递参数onClick(View) 。侦听器绑定为侦听器参数提供了两种选择:您可以忽略方法所有的参数,也可以全部命名。如果你想命名参数,则可以在表达式中使用它们。例如,上面的表达式可以编写如下:

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

或者 在表达式中使用参数

public class Presenter {
    public void onSaveClick(View view, Task task){}
}
android:onClick="@{(theView) -> presenter.onSaveClick(theView, task)}"

超过1个参数您可以使用lambda 表达式

十、导入、变量和 包含

数据绑定库提供了一些功能,例如导入,变量和包含。导入使您可以轻松引用布局文件中的类。变量使您能够描述可在绑定表达式中使用的属性。包括让您在整个应用程序中重复使用复杂的布局。

十、导入

导入使您可以轻松的引用布局文件中的类,就像在托管代码中一样。import 元素内部可以使用零个或多个元素data。

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

组件:

<CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="@{user1.isDefault ? View.VISIBLE : View.GONE}"/>

当类冲突时,可以将其中一个类进行重命名。

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

导入其他类

导入的类型可用作变量和表达式中的类型引用。以下示例显示User并List用作变量类型

 <import type="union.com.viewgroup.jetpack.User" />
        <variable
            name="user1"
            type="User" />
  <import type="java.util.List"/>
        <variable
            name="list"
            type="List&lt;User" />

您也可以使用导入的类型来强制转换表达式的一部分。以下示例将connection属性强制转换为类型User

<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><TextView
   android:text="@{MyStringUtils.capitalize(user.lastName)}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

就像在托管代码一样,java.lang.* 将自动导入。

变量

您可以variable在元素内部使用多个元素data。每个 variable元素都描述了可以在布局上设置的属性,以在布局文件内的绑定表达式中使用。下面的示例声明的userimagenote变量:

<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>

包括

通过使用应用程序名称空间和属性中的变量名称,可以将变量从包含的布局传递到包含布局的绑定中。以下示例显示username.xmlcontact.xml布局文件中包含的变量:

<?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>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值