webentwicklung-frage-antwort-db.com.de

Verwenden der DataBinding-Bibliothek zum Binden von Ereignissen

Ich versuche, Ereignisse mit Ansichten in XML zu binden, indem ich DataBinding Library verwende, die mit Android M geliefert wird. Ich folge Beispiele aus Android Developers und schrittweises Implementieren. Die Attribute der Ansicht wie Sichtbarkeit und Text funktionieren einwandfrei, aber wenn ich versuche, sie mit einem Klick zu binden, funktioniert sie nicht wie erwartet. Hier das Beispiel Code, den ich bisher ausprobiert habe:

 <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}"/>

Hauptaktivität :

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

Ich habe nur erforderlichen Code geschrieben, um die Lesbarkeit zu verbessern. Könnte mir jemand dabei helfen.

42
Pankaj

Ich denke, Sie müssen das handlers auch binden, vielleicht in etwa so in onCreate:

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

Viele Möglichkeiten zum Einstellen von Klicken

1) Handler an Bindung übergeben.

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

2) Klicks setzen (verwenden Sie eine der folgenden Möglichkeiten)

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)}"

Weitere Informationen finden Sie unter Handler-Klasse.

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

Beachten Sie, dass

  • Sie können Methodenreferenz (::) verwenden, wenn Sie dasselbe Argument wie das Attribut onClick haben.
  • Sie können jedes Objekt wie onClickLamdaWithObject übergeben.
  • Wenn Sie das Objekt View übergeben müssen, verwenden Sie einfach (v)-> Ausdruck.

Weitere Lektüre

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

20
Khemraj

Verwenden Sie dieses Format in Ihrer XML:

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

Achten Sie auf die ::, mach dir keine Sorgen über die roten Linien im XML-Editor, denn derzeit ist dies offen Bug für den Android Studio-XML-Editor.

Wobei handlers Ihre Variable aus dem Daten-Tag ist:

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

und onClickFriend ist Ihre Methode:

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

[~ # ~] hinzugefügt [~ # ~]

Fügen Sie für handle onLongClick in xml Folgendes hinzu:

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

und füge die onLongClickFriend Methode in deine ViewModel Klasse ein:

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

[~ # ~] hinzugefügt [~ # ~]

Wenn Sie eine Toastnachricht anzeigen müssen, können Sie die Schnittstelle (bessere Variante) verwenden oder context in der Klasse MyHandlers in construction übergeben:

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

Wenn Sie Ihre Aktivität verwenden möchten, können Sie auch das context -Objekt ersetzen, das automatisch gebunden wird. Andernfalls wird der Speicherplatz verschwendet.

Bei Bedarf wird eine spezielle Variable mit dem Namen context zur Verwendung in Bindungsausdrücken generiert. Der Wert für context ist der Context aus getContext () der Stammansicht. Die Kontextvariable wird durch eine explizite Variablendeklaration mit diesem Namen überschrieben.

binding.setContext(this);

und

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

Beachten Sie, dass es sich bei der Verwendung einer einfachen Zeichenfolge onClick="someFunc" Überhaupt nicht um eine Datenbindungsfunktion handelt. Das ist ein älteres Feature, das ein wenig nachdenklich ist, um die Methode im Kontext zu finden.

4
androidguy

Du solltest tun

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

Ich poste dies nur, um beide Wege zu beschreiben, um dies zu erreichen. 1. durch Listenerbindung 2. durch Methodenreferenz

layout:

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

Aktivität:

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

MyPresenter:

public class MyPresenter{

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


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

// do something
}

}

Hinweis:
1.Während Sie die Methodenreferenz verwenden, sollte die Methodensignatur dieselbe sein, die Sie für jede andere onClick-Methode schreiben würden, dh public und View as parameter.

2.Während Sie die Listener-Bindung verwenden, haben Sie den Vorteil, dass Sie das Objekt auch direkt übergeben können, wenn Sie eine Operation ausführen möchten.

3
Man

Es ist nicht erforderlich, die separate Klasse MyHandlers zu erstellen und setHandlers für die Verarbeitung von Android:onClick Aufzurufen. Sie können einfach die folgenden Methoden verwenden: public void onClickFriend(View view) und public void onClickEnemy(View view) in MainActivity. Die Aktivitätsansicht:

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

Ein Layout:

<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}"/>

Sehen Sie sich das Beispiel für die Verwendung der Datenbindungsbibliothek für das MVVM-Muster an: http://cases.azoft.com/mvvm-Android-data-binding

Ich poste dies, weil ich eine andere Situation hatte, in der dies aufgetreten ist. Wenn Sie zwei Aktivitäten haben, die auf die Layout-Datei verweisen, und eine das Ereignis onclick definiert und die andere nicht dieselbe Warnung und seltsamerweise in der Aktivität, in der Sie das Ereignis definiert haben.

Um dies zu überprüfen, empfehle ich, die Verwendungen der Layoutdatei mit right clicking Auf dem Layoutnamen zu suchen und find references Zu drücken. Vergiss nicht, die App nachträglich neu zu erstellen.

1
jobbert