Лучшая практика для определения событий кнопки в android

У меня есть Layout, определенный в XML, который состоит из нескольких Button s.

В настоящее время я делаю это в методе OnCreate для определения обработчиков событий с помощью кнопок:

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

Внутри события Button onClick я запускаю камеру Intent, чтобы получить изображение и внутри обратного вызова onActivityResult. Я снова устанавливаю обработчики событий вместе с настройкой View следующим образом:

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
}

Я новичок в андроиде, и этот подход переопределения события каждый раз кажется мне грязным. Я хотел бы знать, что лучше всего подходит для определения обработчиков событий кнопок в таких сценариях.

Изменить: вставка моего полного класса

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

    }  

Основной вопрос:

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

Перерегистрация событий внутри onActivityResult.. Правильный подход? Или я делаю что-то неправильно? Потому что, если я не перерегистрирую событие, ничего не происходит, когда я нажимаю кнопку.

Ответ 1

Почему бы не зарегистрировать событие onClick в макете XML, а затем обработать его в коде. Вот как я это сделаю:

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

и теперь создайте метод, который обрабатывал бы клики

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

В качестве альтернативы вы можете установить OnClickListener отдельно для каждого элемента в коде. Затем используйте инструкции if/else или switch для определения начала.

Таким образом, у вас может быть один метод, который обрабатывает все кнопки из одного макета.

UPDATE:
Хотя это действительный подход, я бы настоятельно рекомендовал второй вариант. Это чище и легче поддерживать, особенно когда вы работаете с фрагментами.

Ответ 2

Вот лучший подход с кодом:

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

Новый класс с интерфейсом хорош только в том случае, если вы хотите отделить реализацию (если вы хотите использовать один и тот же код класса в другом месте, переместите его в другой отдельный файл класса и т.д.), но в целом, если вы делаете вещи, связанные с текущей деятельностью, в которой вы находитесь, и реализации onClick зависят от того, как она работает со ссылкой на объекты, определенные там, вы должны обязательно использовать предложенный мной метод.

Создание интерфейсов классов полезно только тогда, когда вы хотите достичь общения между отдельными классами или действиями и держать вещи в стороне. кроме того, что его плохая практика создает подклассы для этого.

Ответ 3

это лучший подход

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

   }
};

Ответ 4

Не существует лучшей практики. Это сильно зависит от варианта использования. Вы можете определить их в своем XML-макете, используя атрибут Button onClick.

Пример XML:

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

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

Таким образом, вам не нужно выполнять OnClickListener самостоятельно. Вы можете назначить каждой кнопке один и тот же метод onClick, а затем просто решить, на основе каждого представления, какое действие нужно вызвать, или у вас может быть отдельный метод для каждой кнопки.

В общем, я советую использовать один OnClickListener для нескольких кнопок. Легче понять, что должен делать каждый слушатель, если вы используете описательные имена, что и должно делать в любом случае.

Ответ 5

Мне нравится "современный" способ DI, используя Butter Knife:

  • Объявите свое мнение
@InjectView(R.id.buttonAlert) 
Button buttonAlert;
  1. Ввести все аннотированные ресурсы
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.inject(this);
 }
  1. Аннотировать и реализовать свой метод onClick.
@OnClick(R.id.buttonAlert)
public void alertClicked(View v){
    // your logic
}

Ответ 6

@Hasan Это лучший подход, который я нашел и который работает для меня каждый раз безупречно.

  • В Layout.xml определите onClick для кнопки

                    <Button android:id="@+id/Button01"          
                        android:onClick="@string/method" 
                        android:focusable="true" android:clickable="true"
                        ">
                    </Button>
    
  • В файле R.string добавьте следующую строку

string name= "method" > buttonFunction

  • В файле sample.java функция define в R.string будет вызываться нажатием кнопки, и она должна выглядеть примерно так:

    public void buttonFunction (Просмотреть вид) { // делать то, что вам нравится при нажатии кнопки }

Ответ 7

В вашей деятельности должен быть реализован OnClickListener, и вы должны написать всю свою обработку событий для всех кнопок внутри одного метода OnCLick().

Ответ 8

Проблема заключается в том, что объект для кнопки newPicButton создается как локальный объект, который действителен только в области действия функции onCreate, и как только код выходит из этой функции, сборщик габаритов освобождает объект для кнопки. вам нужно объявить объект newPicButton вне любого метода, а затем в методе onCreate назначить ему прослушиватель. Это решит вашу проблему, и я надеюсь, что объяснил, почему ничего не происходит, когда вы удаляете код для newPicButton в методе onActivityResult:)

Ответ 9

Я знаю, что это старо, но если кто-то задается вопросом, почему вы не можете добавить onClickListener из onActivityResult, это потому, что кнопка имеет значение null. Если вы снова инициализируете его (как и в onCreate), вы можете добавить слушателя. Однако будьте осторожны, все остальное будет равно нулю, поэтому, если вы берете данные из EditText, например, вы также должны инициализировать это (простая проверка, если объект имеет значение null в lisneter, будет трюк).

Ответ 10

Вот как я это сделал:

  • В кнопках XML файл установлен андроид: onClick = "onClick".
  • В вашей деятельности реализует View.OnClickListener.
  • Внутри метода onClick используйте клавишу Switch (как показано ниже).

@Override

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;

    }
}

Он отлично работает.