Jetpack架构组件DataBinding

基本使用

通常情况下Jetpack组件都是混合一起使用的,这里我们为了讲解,可能会单独使用。

前一篇中我们讲解了ViewModel,终于要介绍大Boos组件DataBinding。
DataBinding是Android上MVVM实现最强大的组件,是 MVVM 模式在 Android 上的一种实现,用于降低布局和逻辑的耦合性,使代码逻辑更加清晰。DataBinding 能够省去我们一直以来的 findViewById() 步骤,大量减少 Activity 内的代码,数据能够单向或双向绑定到 layout。

来看一下怎么使用

datading 入门使用

build.gradle中添加对Databinding的支持。

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

打开布局文件,选中根布局,按住 Alt + 回车键,点击 “Convert to data binding layout”,就可以生成 DataBinding 需要的布局规则。

image

单向数据绑定视图

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

    <data>
        <import type="cn.iwcode.androidjetpack.databind1.UserBean" />
        <variable
            name="userInfo"
            type="UserBean" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".databind1.DataBindActivity1">

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

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{userInfo.phoneNUmber}"/>
    </LinearLayout>
</layout>

layout 标签将原布局包裹了起来,data 标签用于声明要用到的变量以及变量类型。

每个绑定的布局都会生成一个绑定类,ViewDataBinding 的实例名是根据布局文件名来生成,将之改为首字母大写的驼峰命名法来命名,并省略布局文件名包含的下划线。控件的获取方式类似,但首字母小写。

也可以通过class自定义ViewDataBinding实例名

<data class="CustomBinding">

</data>
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_data_bind_1);

    ActivityDataBind1Binding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_data_bind_1);

    UserBean userBean = new UserBean();
    userBean.name = "ygs";
    userBean.phoneNUmber = "18612345678";

    viewDataBinding.setUserInfo(userBean);
}

简单的Model绑定后,如果数据改变并不会让UI自动更新,而我们希望数据改变时,实时刷新UI。

实现数据变化自动驱动 UI 刷新的方式有三种:BaseObservable、ObservableField、ObservableCollection

BaseObservable

BaseObservable有 notifyChange() 和 notifyPropertyChanged() 两个方法刷新数据,

  • notifyChange 刷新所有的字段。
  • notifyPropertyChanged只刷新BR的静态字段,使用@Bindable注解可以生成BR的静态字段。
public class UserBean extends BaseObservable {

    //如果是 public 修饰符,则可以直接在成员变量上方加上 @Bindable 注解
    //如果是 private 修饰符,则在成员变量的 get 方法上添加 @Bindable 注解
    @Bindable
    public String name;

    public String phoneNUmber;

    public int age;

    //更新所有的字段
    public void setAll(String name, String phoneNUmber, int age) {
        this.name = name;
        this.phoneNUmber = phoneNUmber;
        this.age = age;
        notifyChange();
    }
    
    // 只更新name字段
    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }

    public void setPhoneNUmber(String phoneNUmber) {
        this.phoneNUmber = phoneNUmber;
    }
}

在调用setName方法是只更新name字段,而setAll会更新所有的字段。

ObservableField

手动去调用notifyPropertyChanged太麻烦,官方提供了ObservableField包装类。

ObservableField是对 BaseObservable 中字段的注解和刷新等操作的封装,官方原生提供了对基本数据类型的封装,例如 ObservableBoolean、ObservableByte、ObservableChar、ObservableShort、ObservableInt、ObservableLong、ObservableFloat、ObservableDouble 以及 ObservableParcelable ,也可通过 ObservableField 泛型来申明其他类型。

public class UserBean extends BaseObservable {

    public ObservableField<String> name;

    public ObservableField<String> phoneNUmber;

    public ObservableField<Integer> age;

    public void setAll(String name, String phoneNUmber,int age) {
        this.name.set(name);
        this.phoneNUmber.set(phoneNUmber);
        this.age.set(age);
    }

    public void setName(String name) {
        this.name.set(name);
    }
}
ObservableCollection

这个主要是提供对list和map的包装,如ObservableArrayMap,ObservableArrayList。

双向数据绑定

  • 单向绑定:数据改变时 同时视图刷新。
  • 双向绑定:数据改变时 同时视图刷新,视图改变时,也刷新数据

双向绑定给单向绑定就多了一个等号android:text="@={userInfo.phoneNUmber},很简单吧:

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="phone"
    android:text="@={userInfo.phoneNUmber}"/>

事件绑定

我们新建一个事件的类,写几个事件的回调方法:

public class EventViewModel extends ViewModel {

    public void onNameClick(UserBean user){
        Logger.i(user);
    }

    public void onNameClick(View view){
        Logger.i(view);
    }

    public void afterTextChanged(Editable s){
        Logger.i("afterTextChanged: "+s.toString());
    }
}

对应的xml

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

    <data>
        <import type="cn.iwcode.androidjetpack.databind4.UserBean" />
        <variable
            name="userInfo"
            type="UserBean" />

        <import type="cn.iwcode.androidjetpack.databind4.EventViewModel" />
        <variable
            name="eventViewModel"
            type="EventViewModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".databind1.DataBindActivity1">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{()->eventViewModel.onNameClick(userInfo)}"
            android:padding="10dp"
            android:text="@{userInfo.name}"/>

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:afterTextChanged="@{eventViewModel.afterTextChanged}"
            android:padding="10dp"
            android:text="@{userInfo.phoneNUmber}"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{eventViewModel::onNameClick}"
            android:padding="10dp"
            android:text="@{userInfo.name}"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{eventViewModel.onNameClick}"
            android:padding="10dp"
            android:text="@{userInfo.name}"/>

    </LinearLayout>
</layout>

可以看见有3中写法

  • eventViewModel.onNameClick
  • eventViewModel::onNameClick
  • Lambda表达式 ()->eventViewModel.onNameClick(userInfo)

RecycleView

我们来看看databind与Recycleview的简单使用。

Activty类
ActivityDataBind5Binding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_data_bind_5);

MainViewModel viewModel = ViewModelProviders.of(this).get(MainViewModel.class);

viewDataBinding.setViewModel(viewModel);
xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:binding="http://schemas.android.com/apk/res-auto"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <import type="cn.iwcode.androidjetpack.databind5.MainViewModel" />

        <variable
            name="viewModel"
            type="MainViewModel" />
    </data>

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

        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:adapter="@{viewModel.adapter}"
            android:layoutManage="@{viewModel.layoutManage}"/>
    </LinearLayout>
</layout>
MainViewModel类
public class MainViewModel extends ViewModel {

    private RecycleAdapter adapter ;

    private ObservableArrayList<UserBean> listData = new ObservableArrayList<>();

    private void loadData(){
        for (int i = 0;i < 20 ; i++){
            UserBean userBean = new UserBean();
            userBean.name = "ygs-"+i;
            userBean.phoneNUmber = "18612345678";
            userBean.headUrl = "https://avatars1.githubusercontent.com/u/5112053?s=460&v=4";
            userBean.des = "这是描述, 这是描述, 这是描述, 这是描述, 这是描述, 这是描述, 这是描述, 这是描述, 这是描述"+i;
            listData.add(userBean);
        }
    }

    public RecyclerView.LayoutManager layoutManage(){
        return new LinearLayoutManager(APP.mContext);
    }

    public RecycleAdapter adapter(){
        adapter = new RecycleAdapter(listData, APP.mContext);
        loadData();
        return adapter;
    }
}

后面就不贴代码了,有兴趣可以去看一下

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值