Android使用DataBinding实现MVVM模式(基本使用)


简单配置

1.app模块下的build.gradle文件的Android块中,添加:

dataBinding {
        enabled = true
}

2.对生成的layout文件,使用Alt+Enter,转化为binding layout:
图片.png

基本使用(单、双向绑定)

一.定义model

    public class User{
    private ObservableField<String> name ;
    private ObservableField<Integer> age ;
    private ObservableField<String> picUrl ;
    private ObservableField<String> introduce ;


    public User() {
    }

    public User(String name, int age, String picUrl, String introduce) {

        this.name = new ObservableField<>(name);
        this.age = new ObservableField<>(age);
        this.picUrl = new ObservableField<>(picUrl);
        this.introduce = new ObservableField<>(introduce);

    }
    ...  //getter setter
}

如果要实现单、双向绑定,这里的getter 和 setter是不能少的,不能少的,不然会失效。同时,写法是如下:

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

    public void setName(ObservableField<String> name) {
        this.name = name;
    }

不是这种写法:

    public String getName(){
        return name.get();
    }
    
    public void setName(String name){
        this.name.set(name);
    }

或者使用下面的方法:

  • 实体类继承BaseObservale类
  • 在Getter上使用注解@Bindable
  • 在Setter里调用方法notifyPropertyChanged

二.在xml中引入model

    <data>
        <variable
            name="User"
            type="com.xxx.model.User" />
    </data>

使用如下:

        <TextView
            android:id="@+id/textName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{User.name}" />
            
        <TextView
            android:id="@+id/textAge"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(User.age)}" />
        
        <EditText
            android:id="@+id/editIntroduce"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:hint="@string/edit_introduce_hint"
            android:text="@={User.introduce}" />

注意:

  1. int、float等值需要转化为String类型,看源码可以知道,是调用view的seText进行赋值,这个方法的传参必须是String类型的;
  2. 双向绑定,只是在*@*后面加=号

三.添加监听事件

定义事件处理类,类似MVP中的P(这里定义在Activity中):

    public class UserPresenter {
        public void onUpdateIntroduce(User user) {
            Log.e(TAG, "onUpdateIntroduce: " + user.toString());
        }
    }

在xml中引入:

    <data>
        <variable
            name="User"
            type="com.xxx.model.User" />
        <variable
            name="UserPresenter"
            type="com.xxx.view.MainActivity.UserPresenter" />
    </data>

使用:

        <Button
            android:id="@+id/btnSure"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:onClick="@{()->UserPresenter.onUpdateIntroduce(User)}"
            android:text="@string/btn_sure" />

或者使用@UserPresenter::onUpdateIntroduce(User)

四.生成databinding,并给databinding赋值

        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        User user = new User("John", 20, "https://www.xxx.com/img/my_head.jpg", "Hello World");
        binding.setUser(user);
        binding.setUserPresenter(new UserPresenter());

五.使用自定义属性,BindingAdapter

定义一个处理自定义属性的类和方法:

public class ImageViewAdapter {
    @BindingAdapter(value = "url", requireAll = false)
    public static void setImageUrl(ImageView imageView, String url){
        Glide.with(BaseApplication.getContext()).load(url).into(imageView);
    }

使用:

        <ImageView
            android:id="@+id/imagePic"
            android:layout_width="100dp"
            android:layout_height="100dp"
            bind:url="@{User.picUrl}" />

bind声明:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:bind="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

这样就可以使用了,但是这个时候的url,如果填入值,是不会有值匹配显示的,类似这样:

图片.png

可以通过在style中定义一个declare-styleable:

    <declare-styleable name="ImageView">
        <attr name="url"/>
    </declare-styleable>

然后再看:

图片.png

不用指定attr的format,否则一样不显示,但是使用app命名空间就会显示。这个设置不会影响使用,只是少了自动匹配model的属性,以及按住Ctrl跳转的功能。

缺点分析

通过上面的例子可以看到,这里存在2个问题。

  1. 事件触发或其他逻辑操作必须要有一个类似Presenter角色的类持有(不要直接写到model或者Activity中);
  2. model层不得不被改变属性类型,或者不得不加一些注解。

Demo

下一篇文章会介绍经过封装的形式,相对高级一点点

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值