Android DataBinding 的使用姿势

简介: 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)


单项绑定还提供了集合,ObservableMap 和 ObservableList,下面看一下使用方法


看一下布局


<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 适配器中使用,同理,其他的地方都差不多。


相关文章
|
XML 前端开发 JavaScript
Android MVVM模式入门 - DataBinding的使用
Android MVVM模式入门 - DataBinding的使用
501 0
Android MVVM模式入门 - DataBinding的使用
|
Android开发
Android开发教程 - 使用Data Binding(七)使用BindingAdapter简化图片加载
本系列目录 使用Data Binding(一)介绍 使用Data Binding(二)集成与配置 使用Data Binding(三)在Activity中的使用 使用Data Binding(四)在Fragment中的使用 ...
1294 0
|
ARouter 前端开发 Java
MVVM架构结合阿里ARouter,打造一套Android-Databinding组件化
前言 关于Android的组件化,相信大家并不陌生,网上谈论组件化的文章,多如过江之鲫,然而一篇基于MVVM模式的组件化方案却很少。
2143 2
|
Android开发 Kotlin
Android面试题 之 Kotlin DataBinding 图片加载和绑定RecyclerView
本文介绍了如何在Android中使用DataBinding和BindingAdapter。示例展示了如何创建`MyBindingAdapter`,包含一个`setImage`方法来设置ImageView的图片。布局文件使用`&lt;data&gt;`标签定义变量,并通过`app:image`调用BindingAdapter。在Activity中设置变量值传递给Adapter处理。此外,还展示了如何在RecyclerView的Adapter中使用DataBinding,如`MyAdapter`,在子布局`item.xml`中绑定User对象到视图。关注公众号AntDream阅读更多内容。
217 1
|
前端开发 Android开发
Android架构组件JetPack之DataBinding玩转MVVM开发实战(四)
Android架构组件JetPack之DataBinding玩转MVVM开发实战(四)
Android架构组件JetPack之DataBinding玩转MVVM开发实战(四)
|
Android开发 索引 开发工具
Android开发教程 - 使用Data Binding Android Studio不能正常生成相关类/方法的解决办法
本系列目录 使用Data Binding(一)介绍 使用Data Binding(二)集成与配置 使用Data Binding(三)在Activity中的使用 使用Data Binding(四)在Fragment中的使用 ...
1872 0
|
Android开发
Android JetPack组件之DataBinding的使用详解
Android JetPack组件之DataBinding的使用详解
434 0
|
Android开发
Android 使用DataBinding时 将布局页面转换为数据绑定布局(Convert to data binding layout) 不出现提示解决办法
Android 使用DataBinding时 将布局页面转换为数据绑定布局(Convert to data binding layout) 不出现提示解决办法
242 0
|
XML 安全 Android开发
Android Jetpack 之ViewBinding和DataBinding
Android Jetpack 之ViewBinding和DataBinding
1619 1
Android Jetpack 之ViewBinding和DataBinding
|
XML 前端开发 JavaScript
Android基础入门:dataBinding的使用
dataBinding是实现 view 和 data 绑定的工具,把数据映射到 view 的 xml中,可以在 xml 布局文件中实现 view 的赋值,方法调用。使用 DataBinding 后,我们不用再写 findViewById,不用再获取控件对象,不用再设置监听,可以节省我们 activity 中的很多获取控件,赋值,添加监听所需要的代码。 可以说MVP + DataBinding就是MVVC(关于MVC,MVP,MVVC的区别可看往期文章
395 0

热门文章

最新文章