Intereting Posts
Получите уровень звука микрофона в андроиде Идентификатор ресурса не найден для атрибута 'parentActivityName' в пакете 'android' Android notifyDataSetChanged Применение темы к приложению Как создать окружность клипа с изображения? Как я могу предотвратить автоматическую блокировку Android, пока активность (приложение) находится в фокусе? Android PhoneGap приложение не размер содержимого, как эквивалент Chrome / браузер страницу делает Как сделать снимок экрана на экране Android Surface View? Как перейти на предыдущую выбранную вкладку при нажатии кнопки назад панели действий Настройка RecyclerView для работы в чате Эмулятор Google TV не поддерживает локальное воспроизведение и SD-карту? Статистика об устройствах Android с процессорами MIPS Как создать настраиваемый шаблон для Intellij для использования с опцией Guava Использование библиотеки Joda-Time для преобразования String в формат DateTime в API задач Google Как использовать метод setResultCallback?

Лучший способ реализовать 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» не дает никаких практических преимуществ и даже занимает больше памяти. Учитывая количество вложенных классов (и накладных расходов на память), которые мы будем создавать для каждого подобного слушателя, который мы реализуем, этот подход следует явно избегать.

Во-первых, нет никакой лучшей практики, определяемой 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 и имени функции.