Функция
Handler.handleMessage(...)
реализуется в
подклассе
Handler
внутри
onLooperPrepared()
. Функция
HandlerThread.onLooperPrepared()
вызывается до того,
как
Looper
впервые проверит очередь, поэтому она хорошо
подходит для создания реализации
Handler
.
В коде
Handler.handleMessage(...)
мы
проверяем тип
сообщения, читаем значение
obj
(которое имеет тип
T
и
служит идентификатором для запроса) и передаем его функции
handleRequest(...)
.
(Вспомните,
что
Handler.handleMessage(...)
будет вызываться, когда
сообщение загрузки извлечено из очереди и готово к
обработке.)
Вся загрузка осуществляется в функции
handleRequest()
.
Мы проверяем существование URL-адреса, после чего передаем
его новому
экземпляру знакомого класса
FlickrFetchr
. При
этом
используется
функция
FlickrFetchr.getUrlBytes(...)
,
которую
мы
так
предусмотрительно создали в этой главе.
Аннотация
@Suppress("UNCHECKED_CAST")
при проверке
сообщает Lint, что вы приводите
msg.obj
к типу
T
без
предварительной проверки того, относится ли
msg.obj
к этому
типу на самом деле. Это нормально, потому что вы
единственный разработчик, работающий с кодом PhotoGallery.
Вы сами управляете сообщениями, добавленными в очередь, и
знаете, что на данный момент все сообщения в очереди имеют
объектное поле,
установленное в экземпляр
PhotoHolder
(которое
соответствует
T
,
указанному
в
ThumbnailDownloader
).
Реализация обработчика, описанная выше, технически
создает внутренний класс. Внутренние классы содержат ссылку
на
свой
внешний
класс
(в
данном
случае
ThumbnailDownloader
), что в свою очередь может привести к
утечке внешнего класса, если время жизни внутреннего класса
больше, чем предполагаемое время жизни внешнего класса.
Проблемы тут получаются только в том случае, если
обработчик
прикреплен к объекту
Looper
основного потока.
Предупреждение
HandlerLeak
убирается
аннотацией
@SuppressLint("HandlerLeak")
, так как создаваемый
обработчик прикреплен к
looper
фонового потока. Если
вместо этого обработчик был прикреплен к
looper
основного
потока, то он может и не собирать мусор. Если бы произошла
утечка,
так
как
он
также
содержит
ссылку
на
ThumbnailDownloader
, ваше приложение также утеряло бы
экземпляр
ThumbnailDownloader
.
Блокировать предупреждения
Lint нужно только в том
случае, если вы действительно понимаете, откуда взялось
предупреждение и почему его блокирование в данном
сценарии безопасно.
Запустите приложение PhotoGallery и проверьте на панели
LogCat
ваши подтверждающие команды регистрации.
Разумеется, запрос не
будет полностью обработан до
момента назначения изображения в объекте
PhotoHolder
,
поступившем от
PhotoAdapter
. Однако эта операция
относится к пользовательскому интерфейсу, поэтому она
должна выполняться в главном потоке.
До
настоящего
момента
мы
ограничивались
использованием обработчиков и сообщений в одном потоке —
помещением сообщений в
собственный почтовый ящик
ThumbnailDownloader
. В следующем разделе вы увидите, как
ThumbnailDownloader
использует
Handler
для отправки
запросов главному потоку.