web-dev-qa-db-de.com

Best Practice zum Definieren von Schaltflächenereignissen in Android

Ich habe ein Layout in XML definiert, das aus mehreren Buttons besteht. 

Derzeit mache ich dies in der Methode OnCreate, um die Event-Handler anhand der Schaltflächen zu definieren:

public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Button newPicButton = (Button)findViewById(R.id.new_button);
    newPicButton.setOnClickListener(btnListener);
    ..... similarly for other buttons too
    .....
}

Innerhalb des Buttons onClick -Ereignisses starte ich eine Kamera Intent, um ein Bild zu erhalten, und im onActivityResult -Rückruf lege ich wieder die Event-Handler zusammen mit dem View wie folgt:

protected void onActivityResult(int requestCode, int resultCode, Intent data) 
{ 
    setContentView(R.layout.main);
    Button newPicButton = (Button)findViewById(R.id.new_button);
    newPicButton.setOnClickListener(btnListener);
    ...similarly for other buttons too
}

Ich bin neu bei Android und dieser Ansatz, jedes Mal ein Ereignis neu zu definieren, erscheint mir ziemlich schmutzig. Ich würde gerne wissen, was die beste Vorgehensweise ist, um Button-Ereignishandler in solchen Szenarien zu definieren.

Bearbeiten: Meine gesamte Klasse einfügen

public class CameraAppActivity extends Activity 
{
    /** Called when the activity is first created. */

    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button newPicButton = (Button)findViewById(R.id.new_button);
        newPicButton.setOnClickListener(btnListener);
    }

    //---create an anonymous class to act as a button click listener---
    private OnClickListener btnListener = new OnClickListener()
    {

        public void onClick(View v)
        {   
             //Intent newPicIntent = new Intent(v.getContext(), NewPictureActivity.class);
             //startActivityForResult(newPicIntent, 0);
            Intent cameraIntent = new Intent(Android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(cameraIntent, 999);
        } 

    };  

    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    {  

        setContentView(R.layout.main);
        Button newPicButton = (Button)findViewById(R.id.new_button);
        newPicButton.setOnClickListener(btnListener);

       //if I comment last two lines nothing happens when I click on button

    }  

Die Hauptfrage ist

setContentView(R.layout.main);
Button newPicButton = (Button)findViewById(R.id.new_button);
newPicButton.setOnClickListener(btnListener);

Ereignisse in onActivityResult .. erneut registrieren - ist dies der richtige Ansatz? Oder mache ich etwas falsch? Wenn ich das Ereignis nicht erneut registriere, passiert nichts, wenn ich auf die Schaltfläche klicke.

66
Haris Hasan

Warum registrieren Sie das onClick-Ereignis nicht im XML-Layout und behandeln es dann im Code. So würde ich es machen:

<Button
Android:id="@+id/my_btn"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="Click me"
Android:onClick="onBtnClicked">
</Button>

erstellen Sie nun eine Methode, die Klicks verarbeiten kann

public void onBtnClicked(View v){
    if(v.getId() == R.id.my_btn){
        //handle the click here
    }
}

Alternativ können Sie den OnClickListener für jedes Element im Code individuell festlegen. Verwenden Sie dann die Anweisungen if/else oder switch, um den Ursprung zu bestimmen.

Auf diese Weise können Sie eine Methode haben, die alle Schaltflächen eines Layouts behandelt.

UPDATE:
Obwohl dies ein gültiger Ansatz ist, würde ich die zweite Option nachdrücklich empfehlen. Es ist sauberer und einfacher zu warten, insbesondere wenn Sie mit Fragmenten arbeiten.  

63
Marqs

Hier ist der beste Ansatz mit Code:

  public class MyTest extends Activity implements OnClickListener{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
     //... some other code here to init the layout
        Button btn1 = (Button)findViewById(R.id.button1);
        Button btn2 = (Button)findViewById(R.id.button2);
        btn1.setOnClickListener(this);
        btn2.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch(v.getId()){
            case R.id.button1:
                break;
            case R.id.button2:
                break;
        }
    }
}

Die neue Klasse mit einer Schnittstelle ist nur dann gut, wenn Sie die Implementierung abkoppeln möchten (wenn Sie denselben Klassencode an anderer Stelle verwenden möchten, verschieben Sie ihn in eine andere separate Klassendatei usw.) Die aktuelle Aktivität, an der Sie sich befinden, und die OnClick-Implementierungen hängen davon ab, dass sie mit Bezug auf die dort definierten Objekte ausgeführt wird. Sie sollten auf jeden Fall die von mir vorgeschlagene Methode verwenden.

Das Erstellen von Klassenschnittstellen ist nur sinnvoll, wenn Sie die Kommunikation zwischen separaten Klassen oder Aktivitäten erreichen und die Dinge voneinander trennen möchten. Abgesehen davon ist es eine schlechte Praxis, Unterklassen dafür zu erstellen.

39
DArkO

dies ist der beste Ansatz

@Override
public void onCreate(Bundle savedInstanceState) {
        button1.setOnClickListener(onClickListener);
        button2.setOnClickListener(onClickListener);
        button3.setOnClickListener(onClickListener);
}

private OnClickListener onClickListener = new OnClickListener() {
     @Override
     public void onClick(final View v) {
         switch(v.getId()){
             case R.id.button1:
                  //DO something
             break;
             case R.id.button2:
                  //DO something
             break;
             case R.id.button3:
                  //DO something
             break;
         }

   }
};
12

Es ist keine Best Practice definiert. Das hängt stark vom Anwendungsfall ab. Sie können sie in Ihrem XML-Layout mithilfe des onClick-Attributs der Schaltfläche definieren.

XML-Beispiel:

<!-- Stuff -->
<Button Android:id="@+id/my_button"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="Click Me!"
    Android:onClick="myClickMethod" />

Java-Beispiel:

// stuff
public void myClickMethod(View v) {
    // more stuff
}

Auf diese Weise müssen Sie OnClickListener nicht selbst implementieren. Sie können jedem Button die gleiche onClick-Methode zuweisen und dann einfach per View entscheiden, welche Aktion ausgelöst wird, oder Sie können für jeden Button eine eigene Methode verwenden.

Im Allgemeinen rate ich davon ab, einen OnClickListener für mehr als einen Button zu verwenden. Es ist einfacher zu verstehen, was jeder Listener tun soll, wenn Sie beschreibende Namen verwenden. Dies sollten Sie sowieso tun.

8

Ich mag den "modernen" DI-Weg mit Buttermesser :

  1. Erklären Sie Ihre Ansicht
@InjectView(R.id.buttonAlert) 
Button buttonAlert;
  1. Injizieren Sie alle kommentierten Ressourcen
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.inject(this);
 }
  1. Kommentieren und implementieren Sie Ihre onClick-Methode
@OnClick(R.id.buttonAlert)
public void alertClicked(View v){
    // your logic
}
7
funcoder

@Hasan Dies ist der beste Ansatz, den ich gefunden habe und der für mich jedes Mal einwandfrei funktioniert. 

  • Definieren Sie in Layout.xml den onClick für die Schaltfläche

                    <Button Android:id="@+id/Button01"          
                        Android:onClick="@string/method" 
                        Android:focusable="true" Android:clickable="true"
                        ">
                    </Button>
    
  • Fügen Sie in der R.String-Datei die folgende Zeile hinzu

string name = "method"> buttonFunction

  • In der Datei sample.Java wird die in R.string definierte Funktion beim Klicken auf die Schaltfläche aufgerufen und sollte ungefähr so ​​aussehen 

    public void buttonFunction (Ansichtsansicht) { // Machen Sie etwas beim Klicken auf die Schaltfläche }

2
Nitin

So habe ich es gemacht: 

  1. In Buttons XML file set Android: onClick = "onClick".
  2. Implementieren Sie in Ihrem Activity View.OnClickListener.
  3. Verwenden Sie innerhalb der onClick-Methode die Switch-Taste (siehe unten).

@Überfahren

public void onClick(View view) {
    Intent intent;
    switch(view.getId()){

        case R.id.home_button:
            //DO something
            intent = new Intent(HashTagActivity.this,MainActivity.class);
            startActivity(intent);
            break;
        case R.id.back_button:
            //DO something
             intent = new Intent(HashTagActivity.this,ClassActivity.class);
            startActivity(intent);
            break;
        case R.id.favorite_button:
            //DO something
            break;
        case R.id.copy_button:
            //DO something

            break;

    }
}

Es funktioniert großartig.

Ich weiß, das ist alt, aber wenn sich jemand wundert, warum Sie onClickListener nicht aus onActivityResult hinzufügen können, liegt dies daran, dass die Schaltfläche null ist. Wenn Sie es erneut initialisieren (genau wie in onCreate), können Sie den Listener hinzufügen. Seien Sie jedoch vorsichtig. Alles andere wird ebenfalls null sein. Wenn Sie beispielsweise Daten aus einer EditText übernehmen, müssen Sie dies auch initialisieren (eine einfache Überprüfung, ob das Objekt im lisneter null ist, führt den Trick aus ).

0
Yordan Lyubenov

Ihre Aktivität sollte OnClickListener implementieren und Sie sollten Ihre gesamte Ereignisbehandlung für alle Schaltflächen in einer einzigen OnCLick () - Methode schreiben. 

0
Sujit

Das Problem ist, dass das Objekt für die Schaltfläche newPicButton als lokales Objekt erstellt wird, das nur im Gültigkeitsbereich der Funktion onCreate gültig ist. Sobald der Code diese Funktion verlässt, hebt der Garabage-Collector das Objekt für die Schaltfläche auf. Sie müssen das newPicButton -Objekt außerhalb einer Methode deklarieren und dann in der onCreate-Methode einen Listener zuweisen. Dies wird Ihr Problem lösen und ich hoffe, ich habe erklärt, warum nichts passiert, wenn Sie den Code für den newPicButton in der onActivityResult-Methode entfernen :)

0
Nitin