Лучший способ реализовать View.OnClickListener в android

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

Наиболее распространенный способ реализовать это – позволить Activity-Subclass реализовать OnClickListener, что-то вроде этого:

 public class ActivityMain extends Activity implements View.OnClickListener { @Override public void onClick(View view) { switch (view.getId()) { //handle multiple view click events } } } 

Способ, которым я его реализую, – создать частный класс внутри подкласса Activity и позволить этому внутреннему классу реализовать OnClickListener:

 public class ActivityMain extends Activity implements View.OnClickListener { private class ClickListener implements View.OnClickListener { @Override public void onClick(View view) { switch (view.getId()) { //handle multiple view click events } } } } 

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

Более того, говоря о связях «Is-a», «Has-a», последнее кажется хорошей практикой, потому что теперь подкласс Activity-Subclass будет иметь отношение «Has-a» к ClickListener. Хотя в первом методе мы будем говорить, что наш подкласс «Подход» «Is-a» ClickListener, который не совсем прав.

Обратите внимание, что я не занимаюсь служебными данными памяти, которые это вызвало бы.

Кроме того, добавление тега onClick в xml полностью исключается.

Итак, что на самом деле является лучшим способом реализации ClickListener?

Пожалуйста, не предлагайте какие-либо библиотеки, такие как RoboGuice или ButterKnife и т. Д.

ОБНОВИТЬ:

Я хотел бы поделиться подходом, который я наконец принял.

Я непосредственно реализую слушателя в Activity / Fragment.

Что касается дизайна ООП. Подход «HAS-A» не дает никаких практических преимуществ и даже занимает больше памяти. Учитывая количество вложенных классов (и накладных расходов на память), которые мы будем создавать для каждого подобного слушателя, который мы реализуем, этот подход следует явно избегать.

Solutions Collecting From Web of "Лучший способ реализовать View.OnClickListener в android"

Во-первых, нет никакой лучшей практики, определяемой Android относительно регистрации прослушивателей кликов. Это полностью зависит от вашего варианта использования.

Реализация интерфейса View.OnClickListener для Activity – это путь. Поскольку Android настоятельно рекомендует реализацию интерфейса снова и снова, является ли это Activity или Fragment.

Теперь, как вы описали:

 public class ActivityMain extends Activity implements View.OnClickListener { private class ClickListener implements View.OnClickListener { @Override public void onClick(View view) { switch (view.getId()) { //handle multiple view click events } } } } 

Это ваш подход. Теперь это ваш способ реализации, и в этом нет ничего плохого, если вы не беспокоитесь об издержках памяти. Но в чем преимущество создания внутреннего класса и реализации View.OnClickListener если вы можете просто реализовать это в основном классе, что также может привести к ясности и простоте кода, которые вам нужны.

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

Поэтому я предпочел бы обычный способ. Он держит вещи простыми и эффективными. Проверьте код ниже:

 @Override public void onClick(View view) { switch (view.getId()) { //handle multiple view click events } } 

PS: Ваш подход определенно увеличит количество строк кода: P;)

Прежде всего, давайте рассмотрим основы здесь.

Внедряя интерфейс, ваш класс не станет таким .. как вы сказали:

«Наша активность-подкласс» Is-a «ClickListener, что не совсем так».

У вашего класса может быть только отношение «Is-a», если оно распространяется, в данном случае Activity . Реализация интерфейса означает, что он может вести себя так же, как интерфейс установил свой контракт.

Пример:

Класс Питер расширяет Человека .. означает, что Питер – человек.

Класс Питер может также реализовать программиста, музыканта, мужа и т. Д., Что Питер может вести себя как выше.

Что касается лучшей практики, вы можете сделать совершенно отдельный класс, который реализует OnClickListener следующим образом:

 class MyListener implements View.OnClickListener{ @Override public void onClick(View view) { // do whatever you want here based on the view being passed } } 

И в своей основной Activity вы можете создать экземпляр MyListener и вызвать onClick() и передать в нем свое представление:

 MyListener listener = new MyListener(); Button b = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button)findViewById(R.id.button); listener.onClick(button); } 

Я использую button.setOnClickListener(this); Где моя Activity implements View.OnClickListener , а затем получает идентификатор Button в отдельном методе. Ниже приведен пример:

 public class MyActivity extends ActionBarActivity implements View.OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.YOUR_LAYOUT); ... Button myFirstButton = (Button) findViewById(R.id.YOUR_FIRST_BUTTON); myFirstButton.setOnClickListener(this); Button mySecondButton = (Button) findViewById(R.id.YOUR_SECOND_BUTTON); mySecondButton.setOnClickListener(this); ... } ... @Override public void onClick(View v) { Button b = (Button) v; switch(b.getId()) { case R.id.YOUR_FIRST_BUTTON: // Do something break; case R.id.YOUR_SECOND_BUTTON: // Do something break; ... } } ... } 

Я нашел использование Butterknife для чистого кода. И поскольку он использует генерацию кода (а не отражения), он имеет незначительные накладные расходы.

 public class ActivityMain extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.inject(this); } @OnClick(R.id.button_foo) void onFoodClicked() { // Do some foo } @OnClick(R.id.button_bar) void onBarClicked() { // do some bar } } 

Здесь вы можете создать объект btnClickListner, после чего вы будете называть этот объект btnCLickLisner, когда захотите выполнить действия onCLieck для кнопок.

Предположим, что в моей деятельности у меня есть от 5 до 10 кнопок, и каждая кнопка каждого отдельного onclick listner – плохая идея. Чтобы это произошло, мы можем использовать, как показано ниже.

Зарегистрируйте свои кнопки

 Button button1 = (Button)findViewById(R.id.button1); Button button2 = (Button)findViewById(R.id.button2); Button button3 = (Button)findViewById(R.id.button3); Button button4 = (Button)findViewById(R.id.button4); Button button5 = (Button)findViewById(R.id.button5); 

Здесь я устанавливаю onclick listner на мои кнопки после нажатия

 button1.setOnClickListener(btnClickListner); button2.setOnClickListener(btnClickListner); button3.setOnClickListener(btnClickListner); button4.setOnClickListener(btnClickListner); button5.setOnClickListener(btnClickListner); 

Вот реализация btnClick Listner

 View.OnClickListener btnClickListner = new OnClickListener() { @Override public void onClick( View v ) { // TODO Auto-generated method stub if( button1.getId() == v.getId() ) { //Do Button1 click operations here } else if( button2.getId() == v.getId() ) { // Do Button2 clieck operations here } else if( button3.getId() == v.getId() ) { // Do Button3 clieck operations here } else if( button4.getId() == v.getId() ) { // Do Button4 clieck operations here } else if( button5.getId() == v.getId() ) { // Do Button5 clieck operations here } } } 

Ваш ClickListener – это внутренний нестатический класс, связанный с этим «has-a» ничем не отличается от того, что ваш класс Activity реализовал View.OnClickListener . Это потому, что ваш внутренний ClickListener требует экземпляра ActivityMain и действительно не может быть повторно использован. Я бы сказал, что вы закончили инженерную деятельность и на самом деле ничего не набираете.

EDIT: Чтобы ответить на ваш вопрос, мне нравится иметь анонимный View.OnClickListener для каждого виджета. Я думаю, что это создает лучшее разделение логики. У меня также есть такие методы, как setupHelloWorldTextView(TextView helloWorldTextView); Где я поместил всю свою логику, связанную с этим виджетами.

Первый подход лучше, чем другой, потому что именно поэтому View.OnClickListener является Interface вместо abstract class . Кроме того, позже может произойти утечка в различных ситуациях, так как вы используете нестатический внутренний класс.

В этом конкретном случае я бы сказал, что поддерживать единственный экземпляр OnClickListener – лучший подход для вас. У вас будет отношение «Has-a», и вам не нужно будет создавать несколько экземпляров, так как вы обрабатываете поведение, используя идентификатор вида в onClick(View view) .

 public class ActivityMain extends Activity implements View.OnClickListener { private View.OnClickListener mClickListener = new View.OnClickListener() { @Override public void onClick(View view) { switch (view.getId()) { //handle multiple view click events } } }; } 

Просто вы используете, как не реализуете подкласс или не обрабатываете событие click, просто делайте это так.

 android.view.View.OnClickListener method_name = new android.view.View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub // put your code . } }; 

И обрабатывать событие click в кнопку ya любой тип события click, например

 button_name.setOnClickListener(method_name); 

Его работа очень просто Спасибо

Это действительно зависит от того, чего вы хотите достичь. Если у вас есть, например, сложная функциональность с потоками, зависимостями и т. Д., Мне лично нравится полностью отделить ее от Activity в отдельный класс XyzAction , который делает тяжелый материал, знает о некоторых Invoker и возвращает их результаты, если это необходимо. My Invoker s – это в основном объекты, которые реализуют OnClick / OnTouch / etc. Listener и привязываются к необходимым действиям. Например, может быть LoginInvoker реализующий OnClickListener для Button и ImageView а также общий ActionListener который вызывается при нажатии на MenuItem . У Invoker есть методы обновления для отображения прогресса пользователю и результата связанного действия. Сообщения о действиях обновляются до его Invoker и могут быть собраны в мусор, если все они умирают, потому что у него нет связи с пользовательским интерфейсом.

Для менее сложных действий я связываю их непосредственно с компонентом Android (например, Activity / Feagment / View ), а также вызывают их Actions , с большой разницей в том, что они непосредственно выполняют обратные вызовы пользовательского интерфейса.

В обоих случаях я объявляю действия как члены, поэтому я могу быстро взглянуть на конкретные действия, которые поддерживает Android-компонент.

Если есть что-то тривиальное, например, «показывать нажатой кнопку« Toast », я использую анонимные внутренние классы для обратных вызовов пользовательского интерфейса, потому что вам обычно не очень-то интересно о них в отношении ремонтопригодности.

Небольшое замечание к этому и, возможно, немного темы.

Что, если мы не просто реализуем OnClickListener, и у нас есть куча других Listeners / Callback для реализации. В моем мнении он станет беспорядочным, чтобы реализовать все это в классе вместо использования анонимных классов / lambda. Трудно вспомнить, какой метод принадлежит интерфейсу.

Поэтому, если нам нужно реализовать интерфейс (в данном случае OnClickListener) несколько раз, это будет хорошим решением для реализации на базе классов и использования ключа switch / case.

Но если нам нужно реализовать несколько интерфейсов, это может быть хорошим решением для использования анонимных классов / лямбда

Вы можете использовать android:onClick="btn" свойство Button в XML-файле, а затем в java-файле вам не нужно искать идентификатор кнопки. Вам просто нужно сделать одну функцию:

 public void btn(View v){ //======Code that will occur on button click write here====== } 

Помните, что вы должны указать одно и то же имя для имени onClick и имени функции.