Ich habe gelesen, dass Sie onClick
einer Schaltfläche auf zwei Arten einen Handler zuweisen können.
Verwenden Sie das android:onClick
XML-Attribut, bei dem Sie nur den Namen einer öffentlichen Methode mit der Signatur verwenden, void name(View v)
oder verwenden Sie die setOnClickListener
Methode, bei der Sie ein Objekt übergeben, das die OnClickListener
Schnittstelle implementiert . Letzteres erfordert oft eine anonyme Klasse, die ich persönlich nicht mag (persönlicher Geschmack) oder die Definition einer internen Klasse, die das implementiert OnClickListener
.
Wenn Sie das XML-Attribut verwenden, müssen Sie nur eine Methode anstelle einer Klasse definieren. Ich habe mich gefragt, ob dies auch über Code und nicht im XML-Layout möglich ist.
onClick
Attribut in der Layoutdatei verwenden können. Dies geschieht dank des ParametersView v
. Sie überprüfen einfachif (v == findViewById(R.id.button1
)) etc ..v.getId() == R.id.button1
, da Sie nicht die tatsächliche Kontrolle finden und einen Vergleich durchführen müssen. Und Sie können einswitch
statt vieler Wenns verwenden.Antworten:
Nein, das ist per Code nicht möglich. Android implementiert das nur
OnClickListener
für Sie, wenn Sie dasandroid:onClick="someMethod"
Attribut definieren .Diese beiden Codefragmente sind gleich und werden nur auf zwei verschiedene Arten implementiert.
Code-Implementierung
Oben ist eine Code-Implementierung von a
OnClickListener
. Und das ist die XML-Implementierung.XML-Implementierung
Im Hintergrund führt Android nichts anderes als den Java-Code aus und ruft Ihre Methode bei einem Klickereignis auf.
Beachten Sie, dass Android mit dem obigen XML nur in der aktuellen Aktivität nach der
onClick
Methode suchtmyFancyMethod()
. Dies ist wichtig zu beachten, wenn Sie Fragmente verwenden, da Android selbst dann, wenn Sie das obige XML mithilfe eines Fragments hinzufügen, nicht nach deronClick
Methode in der.java
Datei des Fragments sucht, das zum Hinzufügen des XML verwendet wird.Eine andere wichtige Sache, die mir aufgefallen ist. Sie haben erwähnt, dass Sie keine anonymen Methoden bevorzugen . Du wolltest sagen, dass du keine anonymen Klassen magst .
quelle
myFancyMethod()
) in die aktuelle Aktivität einfügen müssen . Dies ist wichtig, wenn Sie Fragmente verwenden, da die programmgesteuerte Methode zum Festlegen von Onclick-Listenern wahrscheinlich die Methode zum Behandeln von Klicks in onCreateView () eines Fragments enthält ... wo es nicht gefunden wird, wenn es aus XML referenziert wird .Als ich die beste Antwort sah, wurde mir klar, dass mein Problem darin bestand, den Parameter (View v) nicht auf die ausgefallene Methode zu setzen:
Wenn Sie versuchen, über die XML darauf zuzugreifen, sollten Sie verwenden
Hoffe das hilft jemandem.
quelle
android:onClick
ist für API-Level 4 und höher. Wenn Sie also auf <1,6 abzielen, können Sie es nicht verwenden.quelle
Überprüfen Sie, ob Sie vergessen haben, die Methode öffentlich zu machen!
quelle
Das Angeben von
android:onClick
Attributen führt dazu, dass dieButton
InstanzsetOnClickListener
intern aufgerufen wird . Daher gibt es absolut keinen Unterschied.Lassen Sie uns zum klaren Verständnis sehen, wie das XML-
onClick
Attribut vom Framework behandelt wird.Wenn eine Layoutdatei aufgeblasen wird, werden alle darin angegebenen Ansichten instanziiert. In diesem speziellen Fall wird die
Button
Instanz mit dempublic Button (Context context, AttributeSet attrs, int defStyle)
Konstruktor erstellt. Alle Attribute im XML-Tag werden aus dem Ressourcenpaket gelesen und anAttributeSet
den Konstruktor übergeben.Button
Klasse wird vonView
Klasse geerbt , was dazu führt, dass derView
Konstruktor aufgerufen wird, der dafür sorgt, dass der Click-Call-Back-Handler über festgelegt wirdsetOnClickListener
.Das Attribut onClick in definierten attrs.xml wird in View.java als bezeichnet
R.styleable.View_onClick
.Hier ist der Code, der
View.java
die meiste Arbeit für Sie erledigt,setOnClickListener
indem er selbst anruft .Wie Sie sehen können,
setOnClickListener
wird aufgerufen, um den Rückruf zu registrieren, wie wir es in unserem Code tun. Der einzige Unterschied ist, dass es verwendetJava Reflection
, dass die in unserer Aktivität definierte Rückrufmethode aufgerufen wird.Hier sind die Gründe für Probleme, die in anderen Antworten erwähnt werden:
Java Class getMethod
verwendet wird, wird nur nach Funktionen mit öffentlichem Zugriffsspezifizierer gesucht. Andernfalls seien Sie bereit,IllegalAccessException
Ausnahmen zu behandeln .getContext().getClass().getMethod()
Aufruf beschränkt die Methodensuche auf den aktuellen Kontext, dh Aktivität bei Fragment. Daher wird die Methode innerhalb der Aktivitätsklasse und nicht innerhalb der Fragmentklasse gesucht.Java Class getMethod
nach einer Methode gesucht wird, dieView.class
als Parameter akzeptiert .quelle
Hier gibt es sehr gute Antworten, aber ich möchte eine Zeile hinzufügen:
In
android:onclick
XML verwendet Android die Java-Reflexion hinter den Kulissen, um dies zu handhaben.Und wie hier erklärt, verlangsamt die Reflexion immer die Leistung. (besonders auf Dalvik VM). Die Registrierung
onClickListener
ist ein besserer Weg.quelle
Beachten Sie, dass die entsprechende Methode einen Parameter haben sollte, dessen Typ mit dem XML-Objekt übereinstimmen sollte, wenn Sie die onClick-XML-Funktion verwenden möchten.
Beispielsweise wird eine Schaltfläche über ihre Namenszeichenfolge mit Ihrer Methode verknüpft.
android:onClick="MyFancyMethod"
Die Methodendeklaration sollte jedoch Folgendes anzeigen:...MyFancyMethod(View v) {...
Wenn Sie versuchen, diese Funktion einem Menüelement hinzuzufügen , hat sie genau dieselbe Syntax in der XML-Datei, aber Ihre Methode wird wie folgt deklariert:
...MyFancyMethod(MenuItem mi) {...
quelle
Eine andere Möglichkeit, Ihre On-Click-Listener festzulegen, ist die Verwendung von XML. Fügen Sie Ihrem Tag einfach das Attribut android: onClick hinzu.
Es wird empfohlen, das XML-Attribut "onClick" nach Möglichkeit über einer anonymen Java-Klasse zu verwenden.
Schauen wir uns zunächst den Unterschied im Code an:
XML-Attribut / onClick-Attribut
XML-Teil
Java-Teil
Anonyme Java-Klasse / setOnClickListener
XML-Teil
Java-Teil
Die Verwendung des XML-Attributs gegenüber einer anonymen Java-Klasse bietet folgende Vorteile:
Natürlich ist es nicht immer möglich, das Xml-Attribut zu verwenden. Hier sind die Gründe, warum wir es nicht gewählt haben:
quelle
Mit Java 8 könnten Sie wahrscheinlich die Methodenreferenz verwenden , um das zu erreichen, was Sie wollen.
Angenommen, dies ist Ihr
onClick
Event-Handler für eine Schaltfläche.Anschließend übergeben Sie
onMyButtonClicked
in einemsetOnClickListener()
Aufruf wie diesem die Instanzmethodenreferenz .Auf diese Weise können Sie vermeiden , eine anonyme Klasse explizit selbst zu definieren. Ich muss jedoch betonen, dass die Methodenreferenz von Java 8 eigentlich nur ein syntaktischer Zucker ist. Es wird tatsächlich eine Instanz der anonymen Klasse für Sie erstellt (genau wie es der Lambda-Ausdruck getan hat), daher wurde eine ähnliche Vorsicht angewendet wie beim Ereignishandler im Lambda-Ausdrucksstil, wenn Sie die Registrierung Ihres Ereignishandlers aufheben. Dieser Artikel erklärt es wirklich schön.
PS. Für diejenigen, die neugierig sind, wie ich die Java 8- Sprachfunktion in Android wirklich nutzen kann, ist dies eine Retrolambda- Bibliothek.
quelle
Ja, Sie können Ihre erstellen
fragment
oderactivity
implementierenView.OnClickListener
und wenn Sie Ihre neuen Ansichtsobjekte im Code initialisieren, können Sie dies einfach tun
mView.setOnClickListener(this);
Dadurch werden automatisch alle Ansichtsobjekte im Code so eingestellt, dass sie die
onClick(View v)
Methode verwenden, die Ihrfragment
oderactivity
usw. hat.Um zu unterscheiden, welche Ansicht die
onClick
Methode aufgerufen hat , können Sie eine switch-Anweisung für diev.getId()
Methode verwenden.Diese Antwort unterscheidet sich von der Antwort "Nein, das ist per Code nicht möglich".
quelle
quelle
Ja, Sie müssen die Methode von Ruivo als "öffentlich" deklarieren, um sie in Android XML onclick verwenden zu können. Ich entwickle eine App, die auf API Level 8 (minSdk ...) bis 16 (targetSdk ...) abzielt.
Ich habe meine Methode als privat deklariert und sie hat Fehler verursacht. Ich habe sie nur als öffentlich deklariert. Das funktioniert großartig.
quelle
Seien Sie vorsichtig, obwohl
android:onClick
XML eine bequeme Möglichkeit zu sein scheint, mit Klicks umzugehen, führt diesetOnClickListener
Implementierung etwas anderes aus als das Hinzufügen vononClickListener
. In der Tat hat es die Eigenschaft viewclickable
auf true gesetzt.Während dies bei den meisten Android-Implementierungen möglicherweise kein Problem darstellt, ist die Schaltfläche laut Telefonkonstruktor standardmäßig immer klickbar = wahr, während andere Konstruktoren in einigen Telefonmodellen in Ansichten ohne Schaltflächen möglicherweise standardmäßig klickbar = falsch sind.
Das Einstellen der XML-Datei reicht also nicht aus. Sie müssen die ganze Zeit überlegen, um sie hinzuzufügen
android:clickable="true"
Nicht-Schaltfläche Wenn Sie ein Gerät haben, auf dem die Standardeinstellung anklickbar ist = true, und Sie einmal vergessen, dieses XML-Attribut einzufügen, werden Sie es nicht bemerken Das Problem zur Laufzeit wird aber das Feedback auf den Markt bekommen, wenn es in den Händen Ihrer Kunden liegt!Darüber hinaus können wir nie sicher sein, wie Proguard XML-Attribute und Klassenmethoden verschleiert und umbenennt, sodass sie nicht 100% sicher sind, dass sie eines Tages niemals einen Fehler haben werden.
Wenn Sie also nie Probleme haben und nie darüber nachdenken möchten, ist es besser,
setOnClickListener
Bibliotheken wie ButterKnife mit Anmerkungen zu verwenden@OnClick(R.id.button)
quelle
onClick
XML - Attribut setzt auch ,clickable = true
weil es ruftsetOnClickListener
auf derView
internAngenommen, Sie möchten ein solches Klickereignis hinzufügen
main.xml
In einer Java-Datei müssen Sie eine Methode wie diese schreiben.
quelle
Ich schreibe diesen Code in eine XML-Datei ...
Und schreibe diesen Code in Fragment ...
quelle
Der beste Weg, dies zu tun, ist mit dem folgenden Code:
quelle
Implementieren Sie eine View.OnClicklistener-Schnittstelle wie folgt, um Ihnen das Leben zu erleichtern und die anonyme Klasse in setOnClicklistener () zu vermeiden:
öffentliche Klasse YourClass erweitert CommonActivity implementiert View.OnClickListener, ...
Dies vermeidet:
und geht direkt zu:
quelle