简体   繁体   English

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

[英]Android two way binding with Integer type causes databinding does not exist

I'm having some issue with implementing two way binding with an Integer data type.我在使用 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:

<?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>

Unfortunately, it gives me the error不幸的是,它给了我错误

"Error:(52, 17) Cannot find the getter for attribute 'android:text' with value type java.lang.Integer on android.support.design.widget.TextInputEditText. " “错误:(52, 17) 在 android.support.design.widget.TextInputEditText 上找不到值类型为 java.lang.Integer 的属性 'android:text' 的 getter。”

If I change the attribute text to如果我将属性文本更改为

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

then I get the error然后我得到错误

"Error:cannot generate view binders java.lang.NullPointerException" “错误:无法生成视图绑定器 java.lang.NullPointerException”

Appreciate any help on this.感谢您对此的任何帮助。

UPDATE: It seems there was another error right after the error mentioned above.更新:在上述错误之后似乎还有另一个错误。

cannot generate view binders java.lang.NullPointerException无法生成视图绑定器 java.lang.NullPointerException

Not sure why its giving me NPE even though the app hasn't started yet.即使应用程序尚未启动,也不知道为什么它给了我 NPE。

Well, six months later but maybe i can help someone.好吧,六个月后,但也许我可以帮助某人。

You can do this simple trick:你可以做这个简单的技巧:

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

OBS .: You need at least Android Studio 2.3 OBS .: 你至少需要Android Studio 2.3

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

Somehow I got this to work by using BindingAdapter and InverseBindingAdapter.不知何故,我通过使用 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());
    }
}

Hopefully this will help someone else as well.希望这也能帮助其他人。

I managed to use Integer.toString(...), doing the import, like this:我设法使用 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>

The previous answer, along with Roberto Leinardi's comment worked perfectly for me!上一个答案以及 Roberto Leinardi 的评论对我来说非常有用! I only have to add is that a null-check should be done to Roberto's check:我只需要补充一点,应该对罗伯托的检查进行空检查:

@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));
    }
}

Here is my solution.这是我的解决方案。 It's clean and simple.它干净而简单。 Simply if layout needs String, give it a String instead of int.简单地如果布局需要 String,给它一个 String 而不是 int。 All you have to do is create a setter and getter with String type and use them to bind to ui while normal setter and getter doing the normal thing!你所要做的就是创建一个 String 类型的 setter 和 getter 并使用它们绑定到 ui,而普通的 setter 和 getter 做正常的事情!

A complete code !一个完整的代码!

My POJO class(Mydata.java).我的 POJO 类(Mydata.java)。 getAgeString and setAgeString are the ui methods, doing the conversion. getAgeStringsetAgeString是 ui 方法,进行转换。 Note that I put @Bindable on getAgeString .请注意,我把@BindablegetAgeString so ui will use ageString所以 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
        }
    }
}

The Layout File(activity_main.xml).布局文件(activity_main.xml)。 use normal two-way binding with @= but use ageString instead of age使用带有@=普通双向绑定,但使用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 file 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());
    }
}

Hope this will help to someone!希望这会对某人有所帮助!

This might help some people who need to get this to work with two way databinding and kotlin.这可能会帮助一些需要使其与双向数据绑定和 kotlin 一起工作的人。

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

import that class in your view在您的视图中导入该类

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

bind it to a textview将其绑定到文本视图

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

The way of using @xdbas's solution使用@xdbas的解决方案的方式

DataBindingConverter.kt数据绑定转换器.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 import 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>
.....

Bind to textView绑定到文本视图

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

Maybe I should have edited his answer but i don't know if it didn't work for him.也许我应该编辑他的答案,但我不知道它是否对他不起作用。

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

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

Then you can do:然后你可以这样做:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM