Главная » Разработка для Android » Использование анонимных классов – JAVA ДЛЯ ANDROID

0

 

Специалисты, имеющие опыт разработки пользовательских интерфейсов, знакомы с концепцией обратного вызова (callback): код должен получить уведомление, когда в пользовательском интерфейсе произойдет какое-либо изменение. Примеры таких изменений – нажатие кнопки или переход модели в какое-то новое состояние. Может быть, из сети пришли новые данные и их нужно отобразить. Вам понадобится способ добавления во фреймворк блока кода, который впоследствии будет выполняться по вашему требованию.

Хотя в языке Java и присутствует идиома для передачи блоков кода, она немного неудобна, так как ни блоки кода, ни методы, не являются в языке объектами первого класса. В языке не предусмотрен способ получения ссылки ни на первые, ни на вторые.

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

Рассмотрим, например, как в Android реализуется механизм отклика на нажатие клавиши пользователем. Класс Android View определяет интерфейс OnKeyListener, который, в свою очередь, определяет метод опКеу. Если код передает View реализацию OnKeyListener, то метод опКеу будет вызываться всякий раз, когда класс View будет обрабатывать новое событие, связанное с нажатием клавиш.

Код может иметь следующий вид:

При создании нового экземпляра класса MyDataModel при помощи аргумента view конструктору сообщается, к какому виду прикрепляется этот класс. Конструктор создает новый экземпляр тривиального класса обратного вызова, KeyHandler, и устанавливает его в вид. Все последующие события, связанные с клавишами, будут передаваться методу handleKey, который относится к экземпляру модели.

Поставленная задача, таким образом, безусловно, решается, однако решение может получиться довольно некрасивым, особенно если классу придется обрабатывать разнохарактерные события, поступающие от разнообразных видов! Через какое-то время все эти определения типов совершенно засорят программу. Определение может быть расположено довольно далеко от использования элемента, а если задуматься – зачем эти определения вообще нужны?

В Java такой код можно несколько упростить, воспользовавшись анонимным классом. Вот фрагмент кода, подобный показанному выше. Но он реализуется с применением анонимного класса:

Конечно, на синтаксический разбор такого кода может понадобиться некоторое время, но он практически идентичен коду из предыдущего примера. Он передает новоиспеченный экземпляр подтипа View.OnKeyListener в качестве аргумента, это делается при вызове view.setOnKeyListener. Но в данном случае аргумент к вызову view. setOnKeyListener использует особый синтаксис, определяющий новый подкласс интерфейса View.OnKeyListener и инстанцирующий его за одну операцию. Новый экземпляр – это экземпляр класса без имени, то есть анонимного класса. Его определение существует только в инстанцирующем его утверждении.

Анонимные классы очень удобны и используются в Java в качестве идиомы для выражения многих разновидностей блоков кода. Объекты, создаваемые с применением анонимных классов, являются в языке объектами «первого класса» и допустимы везде, где мог бы использоваться объект того же типа. Например, возможно такое присваивание:

Может возникнуть вопрос: почему анонимный класс в этом примере делегирует свою фактическую реализацию (метод handl еКеу) объемлющему классу? На самом деле не существует правила, которое бы как-то регламентировало содержимое анонимного класса: он вполне может содержать и полную реализацию. С другой стороны, хорошее понимание идиом подсказывает, что код, изменяющий состояние объекта, следует поместить в класс объекта. Если реализация содержится в объемлющем классе, ее могут использовать другие методы и обратные вызовы. Анонимный класс – просто посредник, в этом и заключается его функция.

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

Проблема снимается, если объявить аргумент к curry как final. Когда мы объявляем его как final, это, конечно же, означает, что его нельзя изменить в анонимном классе. Но для преодоления этой проблемы есть простой идиоматический способ:

Источник: Android. Программирование на Java для нового поколения мобильных устройств

По теме:

  • Комментарии