databinding

资料来源

Android MVVM 系列之 Databinding(一)

曾经有一个梦想

比如一个EditText和一个String变量 name

我希望让EditText自己显示name,当EditText的内容变化时,同步更新到name变量中

现在databinding能实现这个基本功能_双向绑定,这个是Android Studio 2.1 Preview 3之后支持的功能

确保gradle版本不低于2.1.0-alpha3

在gradle的android配置中添加打开databinding功能

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

改写xml文件,用layout节点包裹布局,在layout和布局中添加data节点

这个功能可以添加databinding support插件,支持把现有的布局文件转换成layout包裹的布局

<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>
        <variable
            name="user"

            type="com.example.cleanarchitecturetest.User"/><!--包名路径中不要有大写字母,容易报告找不到类名(因为实际上是包名)-->
    </data>

    <android.support.constraint.ConstraintLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <EditText
            android:id="@+id/tv_store_a"
            android:layout_width="80dp"
            android:layout_height="40dp"
            android:text='@={user.name}'
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.3" />

        <EditText
            android:id="@+id/tv_store_b"
            android:layout_width="80dp"
            android:layout_height="40dp"
            android:text='@={user.age}'
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.9"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.3" />


         <Button
            android:id="@+id/b_show"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="8dp"
            android:text="Button"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />

    </android.support.constraint.ConstraintLayout>
</layout>

User就是一个很简单的数据类,只有自己的成员变量和对应的set/get方法

public class User extends BaseObservable {
    private String name;
    private String age;

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

    public String getName() {
        return name;
    }

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

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

然后,在活动中,添加绑定,改动onCreate方法

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ActivityMainBinding viewBinding=DataBindingUtil.setContentView(this,R.layout.activity_main);
        user=new User("Luohao","18");
        viewBinding.setUser(user);
        intiView();
        
    }

private void intiView() {
        tvStoreA=findViewById(R.id.tv_store_a);
        tvStoreB=findViewById(R.id.tv_store_b);
      
        bStart=findViewById(R.id.b_show);
       
        bShow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                 String name=user.getName();
                 String age=String.valueOf(user.getAge());
                
         Toast.makeText(Main2TestActivity.this,"name="+name+"\nage="+age,Toast.LENGTH_SHORT)
                .show();
            }
        });
    }

这个时候editText中的内容与User.name就互相绑定了

活动初始化时,显示的是User.name和age的值;EditText变化后,点击show按钮,toast会显示User.变化后的属性值,说明双向绑定成功了

注意点:

1,包名路径不能有大写字母,编译器会误认为类名,报错类名找不到

2,编译报错

Cannot find the getter for attribute 'android:text' with value type

这个是因为user的age属性无法正确识别导致,需要重写setText()方法

在user类中添加如下代码(来自overflow

@BindingAdapter("android:text")
    public static void setText(TextView view, int value) {
        view.setText(Integer.toString(value));
    }

    @InverseBindingAdapter(attribute = "android:text")
    public static int getText(TextView view) {
        //    这里是对String变空时,无法正确赋值给age,导致页面崩溃做的优化
        //    除此之外,也需要对editText限定输入值范围
        String value=view.getText().toString();
        if (value.equals("")){
            value="0";
        }
        return Integer.parseInt(value);

 

这样可以做到数据的双向绑定,但是如何应用到mvvm架构里呢

mvvm架构里,UI层与ViewModel层绑定交换数据,而不再是简单的数据类

了解ViewModel参考这里 ViewModels : A Simple Example

这里涉及到在xml文件中引用LiveData的成员变量来设置Text属性

由于暂时只支持get/set方法获取属性,所以建议成员变量设置为Sting/integer等基础类型,而不是类变量

下面时代码

UserModel类,继承ViewModel

public class UserModel extends ViewModel {

    private MutableLiveData<String> name;
    private MutableLiveData<Integer> age;

    public UserModel() {
        name=new MutableLiveData<>();
        name.setValue("wwq");
        age=new MutableLiveData<>();
        age.setValue(28);
    }

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

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

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

    public void setAge(MutableLiveData<Integer> age) {
        this.age = age;
    }
}

布局文件,引用userModel类

<?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>
        <variable
            name="userModel"
            type="com.zy.jetpacktest.viewmodel.UserModel" />
    </data>
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".UI.Main2Activity">

        <EditText
            android:id="@+id/tv_store_a"
            android:layout_width="80dp"
            android:layout_height="40dp"
            android:text='@={userModel.name}'
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.3" />

        <EditText
            android:id="@+id/tv_store_b"
            android:layout_width="80dp"
            android:layout_height="40dp"
            android:text='@={userModel.age}'
            android:digits="0123456789"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.9"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.3" />

        <Button
            android:id="@+id/b_add_a"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="8dp"
            android:text="A_add"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.1"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.5" />

        <Button
            android:id="@+id/b_add_b"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="8dp"
            android:text="B_add"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.9"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.5" />

        <Button
            android:id="@+id/b_show"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="8dp"
            android:text="Button"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Main2Activity

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMain2Binding viewBinding= DataBindingUtil.setContentView(this,R.layout.activity_main2);
        intiView();
        mUserModel = ViewModelProviders.of(this).get(UserModel.class);
        viewBinding.setUserModel(mUserModel);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.b_add_a:
                tvStoreA.setText("测试");
                break;
            case R.id.b_add_b:
                tvStoreB.setText("12345");
                break;
            case R.id.b_show:
                String name= mUserModel.getName().getValue();
                String age= mUserModel.getAge().getValue().toString();
                Toast.makeText(Main2Activity.this,"name="+name+"\nage="+age,Toast.LENGTH_SHORT)
                .show();
                break;
        }
    }

    private void intiView() {
        tvStoreA=findViewById(R.id.tv_store_a);
        tvStoreB=findViewById(R.id.tv_store_b);
        bAddA=findViewById(R.id.b_add_a);
        bAddB=findViewById(R.id.b_add_b);
        bShow =findViewById(R.id.b_show);
        bAddA.setOnClickListener(this);
        bAddB.setOnClickListener(this);
        bShow.setOnClickListener(this);
    }

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值