web-dev-qa-db-fra.com

La liaison à double sens Android avec le type Integer entraîne l’absence de liaison de données

L'implémentation de la liaison bidirectionnelle avec un type de données Integer me pose problème.

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>

Malheureusement, ça me donne l'erreur 

"Erreur: (52, 17) Impossible de trouver le getter pour l'attribut" Android: text " Avec le type de valeur Java.lang.Integer sur Android.support.design.widget.TextInputEditText."

Si je change le texte de l'attribut en 

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

alors j'obtiens l'erreur 

"Erreur: impossible de générer des classeurs de vue Java.lang.NullPointerException"

Appréciez toute aide sur ceci.

UPDATE: Il semble qu'il y ait eu une autre erreur juste après l'erreur mentionnée ci-dessus.

ne peut pas générer de classeurs de vue Java.lang.NullPointerException

Je ne sais pas pourquoi cela me donne du NPE même si l'application n'a pas encore démarré.

17
ank

Eh bien, six mois plus tard, mais je peux peut-être aider quelqu'un.

Vous pouvez faire ce truc simple:

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

OBS.: Vous avez besoin d'au moins Android Studio 2.3

27
Eduvm

D'une manière ou d'une autre, j'ai obtenu ce résultat en utilisant BindingAdapter et 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());
    }
}

J'espère que cela aidera quelqu'un d'autre aussi.

13
ank

La réponse précédente, accompagnée du commentaire de Roberto Leinardi, a parfaitement fonctionné pour moi! Il me suffit d'ajouter que le chèque nul devrait être appliqué au chèque de 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
Daniel Cantoreanu

J'ai réussi à utiliser Integer.toString (...), en effectuant l'importation, comme ceci:

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

3
Fernando Carvalho

Voici ma solution. C'est propre et simple. Si la mise en page nécessite String, donnez-lui une chaîne au lieu de int. Tout ce que vous avez à faire est de créer un setter et un getter avec le type String et de les utiliser pour se lier à l'interface utilisateur pendant qu'un setter et un getter normal font la chose normale!

Un code complet!

Ma classe POJO (Mydata.Java). getAgeString et setAgeString sont les méthodes ui effectuant la conversion. Notez que je mets @Bindable sur getAgeString. alors, je vais utiliser 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
        }
    }
}

Le fichier de mise en page (activity_main.xml). utilisez une liaison bidirectionnelle normale avec @= mais utilisez ageString au lieu de 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>

Fichier 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());
    }
}

J'espère que cela aidera à quelqu'un!

1
mili

Ajoutez ce qui suit dans strings.xml:

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

Ensuite, vous pouvez faire:

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