Каков предпочтительный способ организации обратных вызовов?
В моем проекте Android я определяю несколько обратных вызовов для обработки нажатий кнопок, событий подключения или событий пользовательского интерфейса, таких как Dilaog.onShow(). Для демонстрации я выбрал интерфейс Runnable, который должен быть запущен из некоторого кода Activity. С Java у меня есть разные способы выразить себя.
Один шаблон будет использовать анонимный класс
runOnUiThread(new Runnable() {
public void run() {
doSomething();
}
});
private void doSomething() {
}
другое - определить внутренний закрытый класс, т.е.
private DoSomething implements Runnable {
public void run() {
// do something;
}
}
...
runOnUiThread(new DoSomething());
еще один - использовать приватный член, вот так:
private final Runnable doSomething = new Runnable() {
public void run() {
// do something;
}
}
...
runOnUiThread(doSomething);
Вот еще один, который мне нравится больше всего, потому что, с одной стороны, он на самом деле не создает объекты, если кто-то действительно не использует его, потому что он избегает дополнительных классов, потому что он может принимать параметры при необходимости.
private Runnable doSomething() {
return new Runnable() {
public void run() {
// do something;
}
}
}
...
runOnUiThread(doSomething());
Я не ищу аргументы вкуса или религиозных убеждений, но о возможности сопровождения кода и производительности. Я хотел бы получать советы и подсказки, которые могут помочь мне развить мои собственные предпочтения, возможно - различные предпочтения в соответствии с данным обстоятельством.
Спойлер:
Прогресс Java сделал этот вопрос устаревшим, см. Принятый ответ.
5 ответов
Сегодня, когда Java 8 почти доступна для Android, а Android Studio автоматически делает вид, что лямбды уже поддерживаются, решение анонимного класса (#1) кажется очевидным выбором:
Я не верю, что есть какой-то идиоматический способ обработки обратных вызовов.
Я обычно сначала встраиваю анонимный класс. Когда метод становится слишком большим, я извлекаю создание класса в отдельную функцию. Когда класс становится слишком большим, я извлекаю в свой собственный файл.
Если вы используете IDE, например Eclipse, вы можете выполнять все эти рефакторинги автоматически и безопасно.
Как @Manuel Silva и @Toby Champion, мне не нравятся анонимные внутренние классы. Их несколько трудно читать, они не очень "ОО" в том смысле, что их нельзя расширять, они не могут иметь DIP, сеттеры или что-то еще для настройки поведения и т. Д., И часто заканчивают тем, что нарушают принцип СУХОЙ когда вы добавляете один и тот же код в 27 разных местах.
Я обычно использую закрытые члены (ваш вариант № 3) или частную функцию (ваш четвертый стиль), обычно называемую getAsRunnable().
Я очень новичок в Android, но анонимные классы вызывают у меня тошноту, и кажется, что у вас есть альтернатива runOnUiThread: AsyncTask, обсуждалось здесь: runOnUIThread question
С моей точки зрения, анонимный класс действительно снижает читабельность. Поскольку код пользовательского интерфейса часто очень многословен, добавление анонимных обратных вызовов для каждой кнопки может привести к очень большим классам. Как следствие, я использую внутренние частные классы.