web-dev-qa-db-fra.com

Utilisation de la bibliothèque DataBinding pour les événements de liaison

J'essaie de lier des événements avec des vues au format xml en utilisant la bibliothèque DataBinding fournie avec Android M. Je suis exemples de Développeurs Android et implémentation étape par étape pour les attributs de la vue tels que la visibilité, le texte fonctionne correctement, mais si j'essaie de faire une liaison avec onclick, cela ne fonctionne pas comme prévu. Voici l'exemple de l'exemple code que j'ai essayé jusqu'à présent:

 <data>
    <import type="Android.view.View"/>
    <variable name="user" type="com.example.databinding.User"/>
    <variable name="handlers" type="com.example.databinding.MyHandlers"/>
</data>

 <TextView
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="@{user.firstName}"
    Android:visibility="@{user.isFriend ? View.VISIBLE : View.GONE}" />
 <Button
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="Click Me"
    Android:id="@+id/button"
    Android:layout_gravity="left"
    Android:onClick="@{handlers.onClickFriend}"/>

Activité principale :

  public class MainActivity extends AppCompatActivity {

  User user;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityMainBinding binding = 
    DataBindingUtil.setContentView(this,R.layout.activity_main);
    user = new User("Pankaj","Kumar",true,true);
    binding.setUser(user);
   }
 }

MyHandlers:

public class MyHandlers {
public void onClickFriend(View view){
    Log.i(MyHandlers.class.getSimpleName(),"Now Friend");
}

public void onClickEnemy(View view){
    Log.i(MyHandlers.class.getSimpleName(),"Now Enemy");
  }
}

J'ai écrit seulement le code requis pour améliorer la lisibilité. Quelqu'un pourrait-il m'aider à ce sujet?.

42
Pankaj

Je pense que vous aurez également besoin de lier le handlers, peut-être quelque chose comme ceci dans onCreate:

MyHandlers handlers = new MyHandlers();
binding.setHandlers(handlers);
94
Minhtdh

De nombreuses façons de régler le clic

1) Passez le gestionnaire à la liaison.

ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
Hander handler = new Handler();
binding.setHandlers(handlers);

2) Définissez les clics (utilisez l’un des choix ci-dessous)

Android:onClick="@{handler::onClickMethodReference}"

OR

Android:onClick="@{handler.onClickMethodReference}"

OR

Android:onClick="@{() -> handler.onClickLamda()}"

OR

Android:onClick="@{(v) -> handler.onClickLamdaWithView(v)}"

OR

Android:onClick="@{() -> handler.onClickLamdaWithView(model)}"

Voir la classe Handler pour comprendre.

public class Handler {
    public void onClickMethodReference(View view) {
        //
    }
    public void onClickLamda() {
        //
    }
    public void onClickLamdaWithView(View view) {
        //
    }
    public void onClickLamdaWithObject(Model model) {
        //
    }
}

Notez que

  • Vous pouvez utiliser Référence de la méthode (::) lorsque vous avez le même argument que l'attribut onClick .
  • Vous pouvez passer n'importe quel objet comme onClickLamdaWithObject example.
  • Si vous avez besoin de passer l'objet View, utilisez simplement (v)-> _ expression.

Autres lectures

https://developer.Android.com/topic/libraries/data-binding/expressions

20
Khemraj

Utilisez ce format dans votre XML:

Android:onClick="@{handlers::onClickFriend}"

Faites attention au :: _, ne vous inquiétez pas des lignes rouges dans l'éditeur xml, car c'est actuellement ouvert bug pour l'éditeur Android Studio xml.

handlers est votre variable de balise de données:

<data>
    <variable name="handlers" type="com.example.databinding.MyHandlers"/>
</data>

et onClickFriend est votre méthode:

public class MyHandlers {
    public void onClickFriend(View view) {
        Log.i(MyHandlers.class.getSimpleName(),"Now Friend");
    }
}

[~ # ~] ajouté [~ # ~]

Pour le handle onLongClick au format XML, ajoutez ceci:

Android:onLongClick="@{handlers::onLongClickFriend}"

et ajoutez la méthode onLongClickFriend dans votre classe ViewModel:

public class MyHandlers {
    public boolean onLongClickFriend(View view) {
        Log.i(MyHandlers.class.getSimpleName(),"Long clicked Friend");
        return true;
    }
}

[~ # ~] ajouté [~ # ~]

Si vous devez afficher un message toast, vous pouvez utiliser l'interface (meilleure variante) ou passer context dans la classe MyHandlers en construction:

public class MyHandlers {

    private Context context;

    public MyHandlers(Context context) {
        this.context = context;
    }

    public boolean onLongClickFriend(View view) {
        Toast.makeText(context, "On Long Click Listener", Toast.LENGTH_SHORT).show();
        return true;
    }
}
14
walkmn

Si vous souhaitez utiliser votre activité, vous pouvez également remplacer l'objet context qui est automatiquement lié, sinon vous perdez de l'espace.

Une variable spéciale nommée context est générée pour être utilisée dans les expressions de liaison en fonction des besoins. La valeur de context est le contexte de getContext () de la vue racine. La variable de contexte sera remplacée par une déclaration de variable explicite portant ce nom.

binding.setContext(this);

et

<variable name="context" type="com.example.MyActivity"/>

Notez que si vous utilisez simplement la chaîne onClick="someFunc" ce n'est pas du tout une fonctionnalité de liaison de données. C'est une ancienne fonctionnalité qui utilise un peu de réflexion pour trouver la méthode sur le contexte.

4
androidguy

Tu devrais faire

Android:onClick="@{() -> handlers.onClickFriend()}"
4
Mladen Rakonjac

Je poste ceci juste pour couvrir les deux manières d'y parvenir. 1. par Listener binding 2. par méthode refernce

disposition:

<layout...>
<data>

        <variable
            name="handlers"
            type="com.example.databinding.MyPresenter" />
        <variable name="user" type="com.example.databinding.User"/>
</data>

<LinearLayout
  Android:layout_width="wrap_content"
  Android:layout_height="wrap_content">

    <Button
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_marginTop="32dp"
            Android:text="Using Listener Binding"
            Android:onClick="@{() -> handlers.onLisClick(user)}"/>

     <Button
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_marginTop="32dp"
            Android:text="Using Method Ref"
            Android:onClick="@{handlers::onButtonClicked}"/>            

</LinearLayout>
</layout>

Activité:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding =
                DataBindingUtil.setContentView(this, R.layout.activity_main);
        MyPresenter presenter = new MyPresenter();
        User user = new User("Alex","RJ")
        binding.setUser(user);
        binding.setHandlers(presenter);
    }

Mon présentateur:

public class MyPresenter{

//using listener binding
public void onLisClick(User user){
//do something..
}


//using method reference
public void onButtonClicked(View view){

// do something
}

}

Remarque:
1.Lorsque vous utilisez la référence à la méthode, la signature de la méthode doit être identique à celle que vous écrivez pour toute autre méthode de onClick, c'est-à-dire publique et Voir comme paramètre.

2.Lorsque vous utilisez la liaison d’écoute, vous avez l’avantage de pouvoir transmettre directement l’objet même si vous le souhaitez et de réaliser n’importe quelle opération.

3
Man

Il n'est pas obligatoire de créer la classe séparée MyHandlers et d'appeler setHandlers pour le traitement de Android:onClick. Vous pouvez simplement utiliser les méthodes: public void onClickFriend(View view) et public void onClickEnemy(View view) dans MainActivity. La vue d'activité:

public class MainActivity extends AppCompatActivity {
    User user;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding =
                DataBindingUtil.setContentView(this, R.layout.activity_main);
        user = new User("Pankaj", "Kumar", true, true);
        binding.setUser(user);
    }

    public void onClickFriend(View view) {
        Log.i(MyHandlers.class.getSimpleName(), "Now Friend");
    }

    public void onClickEnemy(View view) {
        Log.i(MyHandlers.class.getSimpleName(), "Now Enemy");
    }
}

Une mise en page:

<data>
    <import type="Android.view.View"/>
    <variable name="user" type="com.example.databinding.User"/>
</data>

<TextView
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="@{user.firstName}"
    Android:visibility="@{user.isFriend ? View.VISIBLE : View.GONE}" />

<Button
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="Click Me"
    Android:id="@+id/button"
    Android:layout_gravity="left"
    Android:onClick="@{onClickFriend}"/>

Regardez l'exemple d'utilisation de la bibliothèque de liaisons de données pour le modèle MVVM: http://cases.azoft.com/mvvm-Android-data-binding

2

Je poste ceci parce que j'ai eu une autre situation dans laquelle ceci s'est produit. Si vous avez deux activités faisant référence au fichier Layout et que l'une définit l'événement onclick et que l'autre ne vous donne pas le même avertissement et étrangement dans l'activité où vous avez défini l'événement.

Pour vérifier cela, je vous recommande de trouver les utilisations du fichier de présentation par right clicking sur le nom de la mise en page et appuyez sur find references. N'oubliez pas de reconstruire les mots suivants de l'application.

1
jobbert