具有整数类型的Android双向绑定导致数据绑定不存在

具有整数类型的Android双向绑定导致数据绑定不存在,android,android-databinding,Android,Android Databinding,我在使用整数数据类型实现双向绑定时遇到了一些问题 public class User { private String firstName; private String lastName; private int age; public User() {} public void setFirstName(String firstName) { this.firstName = firstName; } public

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

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的 android.support.design.widget.text输入文本。“

如果我将属性文本更改为

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

然后我得到了错误

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

谢谢你在这方面的帮助

更新:在上面提到的错误之后,似乎又出现了另一个错误

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


不知道为什么它会给我NPE,即使应用程序还没有启动。

不知何故,我通过使用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());
    }
}

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

前面的答案以及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));
    }
}

六个月后,也许我能帮助别人

您可以执行以下简单的技巧:

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

OBS:您至少需要Android Studio 2.3

这是我的解决方案。它干净简单。如果布局需要字符串,只需给它一个字符串而不是int。您所要做的就是创建一个字符串类型的setter和getter,并在普通setter和getter执行正常操作时使用它们绑定到ui

一个完整的代码

我的POJO类(Mydata.java)
getAgeString
setAgeString
是执行转换的ui方法。注意,我将
@Bindable
放在
getAgeString
上。因此用户界面将使用
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>

希望这将有助于某人

android:text=“@{String.valueOf(Integer)}”
我设法使用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>


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

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

%d
然后你可以做:

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

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

数据绑定转换器.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() ?: ""
        }
    }
}
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 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)}" />

使用@xdbas解决方案的方法

数据绑定转换器.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() ?: ""
        }
    }
}
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>
.....

.....
绑定到文本视图

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


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

也许将
Integer
切换到
int
可以解决这个问题,因为从
String
自动转换为
int
或其他什么。一种很有技巧的方法是将年龄存储为字符串,然后将其转换。在我的用户对象中将Integer更改为int,但仍然得到相同的错误。请尝试将
Integer
替换为
ObservableInteger
。不过,您必须使用方法
.set(SOMENUMBER)
。请参阅以供参考。别忘了使用
Integer.toString()
方法,谢谢你的解决方案,但我仍然有一个问题:我在编辑文本中键入的每个字符都会在文本开头重置光标。你也经历过同样的问题吗?这个问题有什么解决方法吗?好的,我找到了一个解决方案:只有当
视图的文本与
@BindingAdapter(“android:text”)
中的
值不同时,才设置新文本。我必须努力搜索才能找到这个解决方案。这是迄今为止最简单的,应该放在最上面。你知道我在哪里可以找到这方面的文档吗?很抱歉@xerotolerant和你一样,我没有找到任何关于这方面的文档。例如,这可以同时使用double和int值吗?很好的提示!非常感谢。为了以防万一,有些人和我一样,请注意这些符号是反引号(键盘左上角),而不是单引号。注意:这只适用于基本类型,而不是BigDecimal。如果您尝试开始写入负数,它将崩溃(您无法将“-”转换为整数)。这应该是可以接受的。完美而简单!它不允许编辑。问题是关于双向绑定。它还应该支持“@={…}”这是我得到的请:
在com.package.DataBindingConverters类中找不到方法convertIntegerToStringer(java.lang.Integer)
DataBindingConverter.INSTANCE.convertStringToInteger(ViewModel.user.age)