Перевизначення і зворотні виклики – Android

Найпростіша в реалізації сутність – яку розробник зазвичай вибирає для впровадження у фреймворці нового поведінки – це, як правило, зворотний виклик Базова ідея зворотного виклику (даний патерн досить часто зустрічається в бібліотеках Android)

Щоб створити точку розширення для додавання зворотного виклику, в класі визначаються дві речі По-перше, визначається інтерфейс Java (зазвичай його назва закінчується на Handler, Callback або Listener) Цей інтерфейс описує, але не реалізує дію зворотного виклику Крім того, клас визначає метод-інсталятор, який приймає як аргумент той обєкт, який реалізує інтерфейс

Розглянемо додаток, в якому повинен оброблятися текстове введення, одержуваний від користувача Введення, редагування і відображення тексту, зрозуміло, вимагають великого і складного набору класів користувальницького інтерфейсу Але додаток в той же час не повинен вирішувати більшість повязаних з ними завдань Замість цього в компоновку додатки додається бібліотечний ві-джет – скажімо, EditText Фреймворк забезпечує інстанцірованія віджета, відображення його на екрані, оновлення вмісту в міру того, як користувач вводить текст, і т д Тут відбувається все, за винятком завдань, для вирішення яких і призначене ваш додаток (тобто за винятком обробки в коді тексту, що вводиться) Тут і застосовується зворотний виклик

У документації по системі Android вказано, що обєкт Edi tText визначає метод addTextChangedListener, що приймає в якості аргументу обєкт Textwatcher Даний обєкт визначає методи, що активуються, якщо змінюється текст, який міститься в віджеті Зразок коду програми може виглядати так:

MyModel – це центральна частина вашої програми Тут програма приймає текст, що вводиться користувачем, і чинить над цим текстом певні корисні операції При створенні модель MyModel отримує TextBox, тобто отримує поле, в яке користувач буде вводити текст На даний момент ви, напевно, вже встигли набити руку в синтаксичному розборі такого коду У своєму конструкторі MyModel створює нову анонімну реалізацію інтерфейсу TextWatcher Тут же реалізуються три методи, необхідні для цього інтерфейсу Два з них, onTextChanged і beforeTextChanged, нічого не роблять А ось третій метод, afterTextChanged, викликає метод handleTextChange, що відноситься до MyModel

Вся ця система відмінно працює Можливо, два методи, beforeTextChanged і onTextChanged, які не використовуються в даному конкретному додатку, трохи захламляют код Однак за винятком цього моменту в коді дуже красиво реалізується поділ функцій Модель MyModel не уявляє, як TextView відображає текст, де він виводиться на екрані і як у полі потрапляє той чи інший текст Маленький проміжний клас (relay class), анонімний примірник TextWatcher, просто передає змінений текст між видом і MyModel Реалізація моделі MyModel зайнята лише тими подіями, які відбуваються при зміні тексту

Цей процес, в ході якого скріплюються користувача інтерфейс і його поведінки, часто називається підключенням (wiring up) Хоча даний процес досить потужний, з ним також повязано безліч обмежень Клієнтський код – тобто код, який реєструється на отримання зворотного виклику, – не може впливати на поведінку викликає елемента До того ж клієнт не отримує жодної інформації про стан, крім параметрів, що передаються у виклику Тип інтерфейсу (в даному випадку TextWatcher) являє собою явний контракт між відправником зворотного виклику і клієнтом

Існує дію, за допомогою якого клієнт зворотного виклику може впливати на що викликає елемент: клієнт може відмовити у відгуку Клієнтський код повинен сприймати зворотний виклик як звичайне повідомлення, а не як спробу запустити яку-небудь тривалу вбудовану обробку (inline processing) Якщо потрібно виконати небудь значний шматок роботи (тобто більше декількох сотень команд або будь-які виклики, які можуть уповільнити функціонування служб, зокрема служб файлової системи або мережевих служб), то ці команди потрібно поставити в чергу і виконати пізніше, можливо, в іншому потоці Ми детально поговоримо про те, як це робиться, в підрозділі «AsyncTask і потік користувальницького інтерфейсу» розділу «Паралелізм в Android»

Аналогічно служба, яка намагається підтримувати декілька клієнтів зворотних викликів, може відчувати брак ресурсів процесора, навіть якщо всі клієнти працюють відносно добре У той час як addTextChangedListener підтримує можливість підписки для декількох клієнтів, багато зворотні виклики, що входять до складу бібліотеки Android, підтримують тільки один зворотний виклик При роботі з такими зворотними викликами (Наприклад, setOnKeyListener) призначення нового клієнта для певного зворотного виклику, що направляється до конкретного обєкта, призводить до заміни попереднього клієнта, що стояв на цьому місці Зареєстрований раніше клієнт більше не отримуватиме повідомлень про зворотні виклики Насправді він не отримає повідомлення навіть про те, що більше не є клієнтом З цього моменту всі повідомлення буде отримувати клієнт, зареєстрований останнім Таке обмеження, що існує в коді, допомагає вирішити дуже нагальну проблему – таким чином виключається ситуація, в якій зворотний виклик підтримував би необмежену кількість клієнтів Якщо у вашому коді доводиться розподіляти повідомлення відразу між безліччю одержувачів, вам доведеться придумати для цього такий спосіб, який буде безпечний в контексті вашого додатки

Патерн зворотного виклику повсюдно зустрічається в бібліотеках Android Оскільки ця ідіома відома всім розробникам Android, вам теж слід писати свій код за таким принципом Коли якомусь класу потрібні повідомлення про зміни, що відбуваються в інших класах, – особливо при динамічній зміні асоціацій під час виконання – спробуйте реалізувати таке ставлення у вигляді зворотного виклику Якщо відношення не є динамічним, скористайтеся впровадженням залежності (dependency injection), тобто застосуєте параметр конструктора і фінальне поле, щоб зробити необхідну ставлення постійним

Джерело: Android Програмування на Java для нового покоління мобільних пристроїв

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*