使用Integer类型的Android双向绑定导致数据绑定不存在

时间:2016-08-17 13:35:45

标签: android android-databinding

我在使用Integer数据类型实现双向绑定时遇到了一些问题。

public class User {

    private String firstName;
    private String lastName;
    private int age;

    public User() {}

    public void setFirstName(String firstName) {
       this.firstName = firstName;
    }

    public String getFirstName() {
       return this.firstName;
    }

    public void setLastName(String lastName) {
       this.lastName = lastName;
    }

    public String getLastName() {
       return this.lastName;
    }

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

    public int getAge() {
       return this.age;
    }

}

XML:

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

    <data class="UserDataBinding">
        <variable
            name="user"
            type="com.databinding.model.User" />
    </data>

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="@dimen/activity_horizontal_margin">

       <EditText android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@={user.firstName}" />

       <EditText android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@={user.lastName}" />

       <EditText android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@={user.age}" />

    </LinearLayout>
</layout>

不幸的是,它给了我错误

  

“错误:(52,17)无法找到属性'android:text'的getter   值类型为java.lang.Integer on   android.support.design.widget.TextInputEditText。 “

如果我将属性文本更改为

       <EditText android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@={Integer.toString(user.age)}" />

然后我收到错误

  

“错误:无法生成视图绑定器java.lang.NullPointerException”

感谢您的任何帮助。

更新:在上述错误之后,似乎还有另一个错误。

  

无法生成视图绑定器java.lang.NullPointerException

即使应用还没有开始,也不确定为什么它会给我NPE。

9 个答案:

答案 0 :(得分:33)

好吧,六个月后,但也许我可以帮助别人。

你可以做这个简单的伎俩:

android:text="@={`` + mObject.someNumber}"

OBS :您至少需要 Android Studio 2.3

答案 1 :(得分:13)

不知怎的,我使用BindingAdapter和InverseBindingAdapter来实现这一点。

public class User {

    private String firstName;
    private String lastName;
    private int age;

    public User() {}

    public void setFirstName(String firstName) {
       this.firstName = firstName;
    }

    public String getFirstName() {
       return this.firstName;
    }

    public void setLastName(String lastName) {
       this.lastName = lastName;
    }

    public String getLastName() {
       return this.lastName;
    }

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

    public int getAge() {
       return this.age;
    }

    @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) {
        return Integer.parseInt(view.getText().toString());
    }
}

希望这对其他人也有帮助。

答案 2 :(得分:6)

android:text="@{String.valueOf(Integer)}"

答案 3 :(得分:4)

之前的回答以及Roberto Leinardi的评论对我来说非常合适! 我只需要补充的是,应该对Roberto的检查进行无效检查:

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

@BindingAdapter("android:text")
public static void setText(TextView view, int value) {
    if (view.getText() != null
            && ( !view.getText().toString().isEmpty() )
            && Integer.parseInt(view.getText().toString()) != value) {
        view.setText(Integer.toString(value));
    }
}

答案 4 :(得分:4)

我设法使用Integer.toString(...)进行导入,如下所示:

<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="java.lang.Integer" />

        <variable ... />
    </data>

答案 5 :(得分:1)

这是我的解决方案。它干净简单。如果layout需要String,只需给它一个String而不是int。你所要做的就是用String类型创建一个setter和getter,并使用它们绑定到ui,而普通的setter和getter做正常的事情!

完整的代码!

我的POJO课程(Mydata.java)。 getAgeStringsetAgeString是进行转换的ui方法。请注意,我将@Bindable放在getAgeString上。所以ui将使用ageString

package com.databindingnumber;

import android.databinding.BaseObservable;
import android.databinding.Bindable;

public class MyData extends BaseObservable{
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if(this.age != age) {
            this.age = age;
            notifyPropertyChanged(BR.ageString);//NOTE: ui is using ageString !
        }
    }

    @Bindable
    public String getAgeString() {
        return Integer.toString(age);
    }

    public void setAgeString(String ageString) {
        try {
            int val = Integer.parseInt(ageString);
            this.setAge(val);
        }catch(NumberFormatException ex){
            this.setAge(0);//default value
        }
    }
}

布局文件(activity_main.xml)。使用@=的常规双向绑定,但使用ageString代替age

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="foo" type="com.databindingnumber.MyData"/>
    </data>

    <EditText
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:inputType="numberSigned"
        android:text="@={foo.ageString}" />
</layout>

MainActivity.java文件

public class MainActivity extends AppCompatActivity {

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

        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        binding.setFoo(new MyData());
    }
}

希望这会对某人有所帮助!

答案 6 :(得分:1)

这可能会帮助需要使用双向数据绑定和Kotlin的某些人。

DataBindingConverter.kt

class DataBindingConverter {
    companion object {

        @InverseMethod("convertStringToInteger")
        @JvmStatic
        fun convertIntegerToString(value: String): Int? {
            if (TextUtils.isEmpty(value) || !TextUtils.isDigitsOnly(value)) {
                return null
            }

            return value.toIntOrNull()
        }

        @JvmStatic
        fun convertStringToInteger(value: Int?): String {
            return value?.toString() ?: ""
        }
    }
}

在您的视图中导入该类

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <import type="com.package.DataBindingConverter" />
    </data>
.....

将其绑定到textview

<EditText
    ...
    android:text="@={DataBindingConverter.convertStringToInteger(ViewModel.user.age)}" />

答案 7 :(得分:0)

在strings.xml中添加以下内容:

<resources>
    <string name="_int">%d</string>
</resources>

那么您可以做:

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{@string/_int(user.age)}" />

答案 8 :(得分:0)

使用@xdbas解决方案的方式

DataBindingConverter.kt

class DataBindingConverters {
    companion object {

        @InverseMethod("convertIntegerToString")
        @JvmStatic
        fun convertStringToInteger(value: String): Int? {
            if (TextUtils.isEmpty(value) || !TextUtils.isDigitsOnly(value)) {
                return null
            }
            return value.toIntOrNull()
        }

        @JvmStatic
        fun convertIntegerToString(value: Int?): String {
            return value?.toString() ?: ""
        }
    }
}

XML导入

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <import type="com.package.DataBindingConverter" />
    </data>
.....

绑定到textView

<EditText
    ...
    android:text="@={DataBindingConverter.convertStringToInteger(ViewModel.user.age)}" />

也许我应该编辑他的答案,但是我不知道这是否对他不起作用。