Android DataBinding 的使用姿势

DataBinding 的使用

DataBinding 一般情况下很少使用,但是如果你要使用 MVVM 框架,那么 DataBinding就是必不可少的了。下面我们看一下他的用法:

准备工作

​ 先在使用的 module 中添加如下

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

简单的使用:

1,创建 Bean 类
public class UserBean  {

    private String name;
    private int age;
    ......
}
2,布局文件
<layout xmlns:android="http://schemas.android.com/apk/res/android">

   <data>
       <variable
           name="User"
           type="www.testdemo.com.UserBean"/>
   </data>

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

        <TextView
            android:id="@+id/age"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(User.age)}"
            android:textColor="@color/black"
            android:textSize="20sp" />

        <TextView
            android:id="@+id/name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{User.name}"
            android:textColor="@color/black"
            android:textSize="20sp" />

    </LinearLayout>

</layout>

修改根视图为 layout,添加 data 标签,variable 标签就相当于一个数据类,name 为名字,type 为地址。

然后在 要使用的地方使用 定义的 name.属性即可,如上面的 TextView,注意 TextView 值必须是 String,所以对 age 进行了强转

3,在代码中使用
ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main); 
UserBean bean = new UserBean("张三",20);
activityMainBinding.setUser(bean);

运行程序,就会发现数据已经自动显示到上面了。

注意,因为 布局的名字是 activity_main ,所以这是使用的是 ActivityMainBinding。这个类是系统根据布局文件的名字自动生成的。

4,一处多用

​ 如果 bean 类在布局的多个地方使用,且值不一样,该怎么办,如下所示:

​ 修改布局如下:

<data>
        <import type="www.testdemo.com.UserBean" />

        <variable
            name="User1"
            type="UserBean" />

        <variable
            name="User2"
            type="UserBean" />

        <variable
            name="User3"
            type="UserBean" />
</data>

使用 import 导入Bean 类,然后在下面设置多个数据类即可。

​ 使用:

 activityMainBinding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);
        bean = new UserBean("张三",23);
        bean1 = new UserBean("李四",24);
        bean2 = new UserBean("王五",25);
        activityMainBinding.setUser1(bean);
        activityMainBinding.setUser2(bean1);
        activityMainBinding.setUser3(bean2);

当布局修改为上面的之后,你就会发现可以设置多种 bean 类了。在布局中使用还是 name.xxx,例如 User3.age

问题:如果导入的路径不同,但是类名相同那该如何是好!如下所示:

<import type="www.testdemo.com.UserBean"/>
<import type="www.testdemo.com.bean.UserBean"/>

这个时候就可以使用 alias 属性了:

<data>
        <import type="www.testdemo.com.UserBean" />
        <import
            alias="BeanUser"
            type="www.testdemo.com.bean.UserBean" />

      <!--第一个 import-->
        <variable
            name="User1"
            type="UserBean" />

        <!--第二个 import-->
        <variable
            name="Bean1"
            type="BeanUser" />

        <!--第二个 import-->
        <variable
            name="Bean2"
            type="BeanUser" />
    </data>

默认值 default

 <TextView
            android:id="@+id/name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{User.name ,default= 哈哈哈}"
            android:textColor="@color/black"
            android:textSize="20sp" />

单项绑定( BaseObservable )

BaseObservable 有两个方法

//全局刷新
notifyChange();
//局部刷新
notifyPropertyChanged(BR.name);

Bean 继承 BaseObservable

UserBean 如下:

public class UserBean extends BaseObservable {

    @Bindable
    public String name;
    private int age;

    public UserBean(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        this.age = age;
        //全局刷新
        notifyChange();
    }

    public void setName(String name) {
        this.name = name;
        //局部刷新
        //如果 BR中调不出来属性,就需要 Rebuild 一下
        notifyPropertyChanged(BR.name);
    }
}

​ 如果在设置某个属性的时候需要全局刷新,在 set 方法中调用notifyChange() 即可。 如果需要对某个属性进行刷新,则在set方法里面进行局部刷新即可。

​ 上面给 age 全局刷新,给 name 局部刷新。

​ 注意:如果需要局部刷新,那么他所刷新的字段必须为 public 类型,且必须使用 @Bindable 注解。

使用:


        ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);
        bean = new UserBean("张三",20);
        activityMainBinding.setUser(bean);

        findViewById(R.id.main_b).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //直接给类设置值,ui会自动改变
                bean.setAge(1000);
                bean.setName("王五");
            }
        });

事件回调中,设置了值,猜一下结果如果

​ 结果:两个值都被刷新了,虽然 name 是局部刷新,但是 age 是全局。所以值都刷新了,你可以试一下取消全局刷新,看一下效果。


点击事件

​ @{()-> listener.changeName()}

​ 添加事件类

  public class OnListener{
        public void changeAge(){
            Toast.makeText(MainActivity.this, "haha", Toast.LENGTH_SHORT).show();
            bean.setAge(1000);
        }
        public void changeName(){
            bean.setAge(30);
            bean.setName("王五");
        }
    }

​ 修改布局

  <data>
        <variable
            name="user"
            type="www.testdemo.com.UserBean"/>

        <!-- 点击事件 -->
        <import type="www.testdemo.com.MainActivity.OnListener"/>
        <variable
            name="listener"
            type="OnListener"/>
    </data>

<-- 增加两个 Button -->
    
      <Button
            android:id="@+id/main_b"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{()-> listener.changeAge()}"
            android:background="#fff000" />

        <Button
            android:id="@+id/main_c"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#fff000"
            android:onClick="@{()-> listener.changeName()}" />

进行绑定:
ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);
bean = new UserBean("张三",20);
activityMainBinding.setUser(bean);
//绑定事件
activityMainBinding.setListener(new OnListener());

​ 然后点击 Button ,那两个方法就会得到执行


单项绑定(ObservableField)

​ 使用单项绑定刷新 UI 的有三种

​ 1,BaseObservable

​ 2,ObservableField

​ 3,ObservableCollection

​ 这次我们 看一下第二种,记得第一种方法用于来特别麻烦,又要注解,还要 set 方法。

​ 第二种就简单多了,只需要将 字段用 public final 进行修饰,然后重写 get 方法即可,如下:

public class UserBean extends BaseObservable {

   public final ObservableField<Integer> age;
   public final ObservableField<String> name;

    public UserBean( ObservableField<String> name,  ObservableField<Integer> age) {
        this.name = name;
        this.age = age;
    }

    public ObservableField<Integer> getAge() {
        return age;
    }

    public ObservableField<String> getName() {
        return name;
    }
}

布局不需要修改

使用如下:

public class MainActivity extends AppCompatActivity {
    private UserBean bean;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);
        bean = new UserBean(new ObservableField<String>("张三"), new ObservableField<Integer>(20));
        activityMainBinding.setUser(bean);
        activityMainBinding.setListener(new OnListener());
    }
    
    //点击事件
    public class OnListener {
        public void changeAge() {
            bean.getAge().set(200);
        }

        public void changeName() {
            bean.getAge().set(30);
            bean.getName().set("王五");
        }
    }
}

是不是非常简单呢!


单项绑定(ObservableCollection)

​ 单项绑定还提供了集合,ObservableMapObservableList,下面看一下使用方法

​ 看一下布局

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
     <!-- map 集合 -->
        <import type="android.databinding.ObservableMap" />

        <variable
            name="user"
            type="ObservableMap&lt;String,Object&gt;"/>

    </data>

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

        <TextView
            android:id="@+id/name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text='@{String.valueOf(user["马六"])}'
            android:textColor="@color/black"
            android:textSize="20sp" />

        <TextView
            android:id="@+id/name1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text='@{String.valueOf(user["王五"])}'
            android:textColor="@color/black"
            android:textSize="20sp" />

    </LinearLayout>
</layout>

在 data 标签中使用了 map 数组 注意 type 的值 ,那两个&后面的代表是尖括号 < 和 > ,然后在 TextView 中通过查找 键来获取值

注意 TextView 的 text 后面是 ’ ',并不是 “ ”

在代码中使用:

 ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);

        ObservableMap<String,Object> map = new ObservableArrayMap<>();
        map.put("王五",65);
        map.put("马六",80);
        activityMainBinding.setUser(map);

ObservableList 的使用

修改布局:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
    <import type="android.databinding.ObservableList" />
    <variable
        name="user"
        type="ObservableList&lt;String&gt;"/>

</data>

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

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text='@{String.valueOf(user[0])}'
        android:textColor="@color/black"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/name1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text='@{String.valueOf(user[1])}'
        android:textColor="@color/black"
        android:textSize="20sp" />

</LinearLayout>
</layout>

使用如下:

 ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);

        ObservableList<String> list = new ObservableArrayList<>();
        list.add("王五");
        list.add("马六");
        activityMainBinding.setUser(list);

双向绑定

​ 简单解释一下:就是数据发生改变 ui 立刻刷新,ui 变化 数据也会改变。

​ 看一下 Bean 类:

public class UserBean extends BaseObservable {  
    public final ObservableField<String> string;
    public UserBean( ObservableField<String> string) {
        this.string = string;
    }

    public ObservableField<String> getString() {
        return string;
    }
}

布局

<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
   <variable
       name="user"
       type="www.testdemo.com.UserBean"/>
</data>

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

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text='@{user.string}'
        android:textColor="@color/black"
        android:textSize="20sp" />

    <EditText
        android:id="@+id/edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@={user.string}"
        android:hint="请输入数据"/>

</LinearLayout>
</layout>

​ 上面一个 一个 editText,一个 TextView,注意他们 text 的内容

  ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);
        userBean = new UserBean(new ObservableField<>("345"));
        activityMainBinding.setUser(userBean);

​ 运行,在 EditText 中输入内容,textView 内容也会跟着改变,反之也一样。


引用类方法

​ 如下面这个类,有一个静态方法:

public class Data {
    public static String setString(String s){
        return s+" ------";
    }
}

​ 那么就可以在布局中直接调用他。如下:

<import type="www.testdemo.com.Data"/>

 <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text='@{Data.setString(user.string)}'
        android:textColor="@color/black"
        android:textSize="20sp" />

​ 只贴出了有用的代码,在 text 属性中 调用了 Data 的 setString 方法,这个 TextView 显示的就是 setString 返回的字符串

注意:只能够调用静态方法


使用运算符

<TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text='@{user.age + user.name}'
        android:textColor="@color/black"
        android:textSize="20sp" />
            
<TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text='@{String.valueOf(1+2)}'
        android:textColor="@color/black"
        android:textSize="20sp" />
           
<TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text='@{String.valueOf(1+2)}'
        android:textColor="@color/black"
        android:textSize="20sp"
        android:visibility="@{user.status ? View.VISIBLE : View.GONE}"/>    

在适配器中使用

​ 简单的看一下就好:

 @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        ItemNewsBinding itemNewsBinding = DataBindingUtil.inflate(LayoutInflater.from(mContext), R.layout.item_news,parent,false);
        return new ViewHolder(itemNewsBinding);
    }

这个是在 RecyclerView 适配器中使用,同理,其他的地方都差不多。

参考:https://blog.csdn.net/qq_40881680/article/details/102240892

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tʀᴜsᴛ³⁴⁵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值