Was ist der richtige Weg, um die OnClickListener-Schnittstelle für viele Schaltflächen zu implementieren?

10

Meine Android-Aktivität enthält mehrere Schaltflächen, die alle einen OnClickListener benötigen. Ich habe viele verschiedene Möglichkeiten gesehen, wie ::

  • Implementierung der Schnittstelle in der Aktivitätsklasse
  • Erstellen einer separaten Klasse, die die Schnittstelle implementiert
  • Definieren einer anonymen inneren Klasse für jede Schaltfläche.

Ich habe viele Beispiele für jeden Ansatz gesehen. Mir ist jedoch nicht klar, warum ein Ansatz anstelle eines anderen verwendet wird. Sind die Unterschiede zwischen diesen Ansätzen stilistisch oder gibt es Gründe, die einen Ansatz besser machen?

Slayton
quelle

Antworten:

6

Wie bei vielen Dingen hängt der richtige Ansatz davon ab, was Sie für die jeweilige Schaltfläche versuchen und was Sie sonst noch mit der Aktivität tun.

Aktivitätsklasse implementiert Schnittstelle :
Dies ist eine gute Option, wenn Sie nur einen Aufgabentyp ausführen müssen, wenn dieser Listener aufgerufen wird. Ein Beispiel hierfür wäre ein einfaches Formular mit einer Reihe von Feldern und einer Schaltfläche zum Speichern. Ich möchte, dass mein Ereignis-Listener die Quelle des Ereignisses nicht überprüft, um zu entscheiden, was tatsächlich getan werden muss. Ich weiß, dass einige vielleicht sagen, dass dies eine Stilsache ist, aber ich glaube, dass es einfacher ist, dem Code zu folgen, wenn der Listener diese Prüfung nicht durchführen muss, da Sie genau wissen, was für jedes Ereignis aufgerufen wird.

Eine andere Klasse implementiert die Schnittstelle :
Wie oben erwähnt, bevorzuge ich diese Option, wenn ich mehrere Elemente habe, die dasselbe Ereignis auslösen können. Wenn Sie das obige Beispiel erweitern, können Sie eine Schaltfläche zum Löschen hinzufügen, für die auch ein Klick-Listener erforderlich ist. Erstellen Sie einen Listener, der die Speicheraktionen ausführt, und einen Listener, der die Löschaktionen ausführt. Jeder Listener wird nur zu den Komponenten hinzugefügt, die diese Aktion erzeugen.

Diese Implementierung bietet einen zusätzlichen Vorteil, den Sie nutzen können, wenn Sie sich darum kümmern. Der Vorteil besteht darin, dass andere Klassen das Ereignis innerhalb Ihrer Aktivitätsklasse nicht auslösen können. Da die Schnittstellenmethode öffentlich sein muss, kann jeder mit einem Verweis auf die Klasse das Ereignis auslösen. Wenn Sie genau steuern möchten, wer was in der Anwendung tun kann, verhindert eine separate Klasse, dass Personen mit einem Verweis auf die Aktivität das Löschen oder Speichern Ihres Formulars auslösen (oder möglicherweise den Code beschädigen, wenn der Listener die Quelle verwendet, dies jedoch tut nicht mit schlechten Eingaben umgehen).

Eine anonyme innere Klasse implementiert die Schnittstelle :
Dies ist wirklich nur eine spezielle Methode, um die zweite Option zu konstruieren, eine andere Klasse als Implementierung zu verwenden. Diese Option kann noch weiter einschränken, wer Zugriff hat, um das Ereignis auszulösen, da niemand sonst eine Instanz der Klasse erstellen kann. Ich denke jedoch, der wichtigere Faktor zwischen den beiden Optionen ist, wie viel Arbeit geleistet wird. Das Löschen einiger Textfelder ist einfach und unkompliziert. Das Speichern des for kann jedoch eine Reihe von Aufgaben umfassen: Sie validieren die Eingabe (was Sie tun sollten), schreiben in eine Datenbank, um die Werte zu speichern, und lösen eine Aktion nach dem Speichern aus. In diesem Fall wird durch Erstellen einer separaten Klasse mit einer eigenen Datei eine klarere Trennung zwischen dem Eingabeformular und der Datenverarbeitung erzielt. Dadurch bleibt der Formularcode anstelle einer größeren Datei mit mehreren darin verschachtelten inneren Klassen erhalten.

unholysampler
quelle
Wow, danke für deine Antwort. Ist es in Bezug auf den Overhead teurer, mehrere Listener-Klassen zu erstellen?
Slayton
@slayton: Es wird immer Kosten geben, egal was du tust. Die Frage sollte lauten: "Ist der Unterschied für Sie wichtig?" Es ist wichtig, mehr Objekte zu erstellen, aber die Ausführungszeit ist länger, wenn Ihr Listener eine Liste von Quellen durchgehen muss, um zu entscheiden, was tatsächlich zu tun ist. Wenn die Speichernutzung und -leistung für Sie wichtig sind, sollten Sie den Code profilieren und anhand Ihrer Anforderungen entscheiden, was am besten ist. Ich würde jedoch bezweifeln, dass dies der Flaschenhals Ihres Codes ist. Treffen Sie Ihre Entscheidungen, bis der Code klarer und besser organisiert ist, sofern nichts anderes angezeigt wird.
Unholysampler
3

Eine vierte Möglichkeit besteht darin, das onClick-Attribut im Layout festzulegen:

<Button android:onClick="clickHandlerForButtonX" />

welches diese entsprechende Methode in der Aktivität hat:

public void clickHandlerForButtonX(View v) {
    //Handle Button X here
}
Orjan
quelle
Interessant, ich wusste nicht, dass du das kannst. Obwohl dies ein Android-spezifischer Mechanismus für den Umgang mit Tastenklicks zu sein scheint.
Slayton
Normalerweise gehe ich jedoch mit der "Aktivitätsklasse implementiert Schnittstelle" - auf diese Weise haben Sie alle klickbezogenen Dinge an derselben Stelle.
Orjan
Diese spezielle Methode funktioniert nicht mit Fragmenten.
Rahul Tiwari