name="colorAccent">@color/colorAccent
name="AppTheme"
parent="Theme.AppCompat.Light.DarkActionBar">
name="StrongBeatBoxButton"
parent="@style/BeatBoxButton">
bold name="AppTheme"
parent="Theme.AppCompat.Light.DarkActionBar">
...
name="AppTheme"
parent="Theme.AppCompat
.Light.DarkActionBar
">
...
name="AppTheme"
parent="Theme.AppCompat">
name="colorPrimary">@color/
colorPrimaryred<
/item>
name="colorPrimaryDark">@color/
colorPrimary
Darkdark_red
name="colorAccent">@color/
colorAccentgray
item>
name="Theme.AppCompat"
parent="Base.Theme.AppCompat" />
Тема
Theme.AppCompat
наследует
атрибуты
от
Base.Theme.AppCompat
. Интересно, что
Theme.AppCompat
не
переопределяет никакие атрибуты, а только содержит ссылку
на своего родителя.
Щелкните мышью по
Base.Theme.AppCompat
с нажатой
клавишей (
Ctrl ). Android Studio сообщит, что тема уточняется
по ресурсам. Существует несколько разных версий этой темы в
зависимости от используемой версии Android.
name="Base.Theme.AppCompat"
parent="Base.V7.Theme.AppCompat">
name="Base.V7.Theme.AppCompat"
parent="Platform.AppCompat">
androidx.appcompat.app.AppCompatVie
wInflater false true name="windowActionBarOverlay">false
name="Platform.AppCompat"
parent="android:Theme.Holo">
name="android:windowNoTitle">true
name="android:windowActionBar">false
?
attr/buttonBarStyle ?
attr/buttonBarButtonStyle name="android:borderlessButtonStyle">?
attr/borderlessButtonStyle
...
name="Platform.AppCompat"
parent="android:Theme.Holo">
...
...
name="android:windowBackground">@color/backgrou
nd_material_dark
name="AppTheme"
parent="Theme.AppCompat">
@color/red name="colorPrimaryDark">@color/dark_red
@color/gray name="android:windowBackground">@color/soothing _blue name="Base.V7.Theme.AppCompat"
parent="Platform.AppCompat">
...
name="buttonStyle">@style/Widget.AppCompat.Butt
on
name="buttonStyleSmall">@style/Widget.AppCompat
.Button.Small
...
name="Widget.AppCompat.Button"
parent="Base.Widget.AppCompat.Button"/>
Стиль
Widget.AppCompat.Button
самостоятельно никакие
атрибуты не определяет. Чтобы просмотреть его содержимое,
перейдите к его родителю. Вы увидите, что базовый стиль
существует
в
двух
версиях.
Выберите
версию
values/values.xml
.
name="Base.Widget.AppCompat.Button"
parent="android:Widget">
name="android:background">@drawable/abc_btn_def
ault_mtrl_shape
?
android:attr/textAppearanceButton 48dip 88dip true true name="android:gravity">center_vertical|center_h
orizontal
name="AppTheme"
parent="Theme.AppCompat">
name="colorPrimary">@color/red
name="AppTheme"
parent="Theme.AppCompat">
name="colorPrimary">@color/red
name="colorPrimaryDark">@color/dark_red
name="colorAccent">@color/gray
name="android:windowBackground">@color/soothing
_blue
name="BeatBoxButton"
parent="Widget.AppCompat.Button">
name="android:background">@color/dark_bluem>
name="Platform.AppCompat"
parent="android:Theme.Holo">
...
name="AppTheme"
parent="Theme.AppCompat">
...
name="BeatBoxButton"
parent="Widget.AppCompat.Button">
name="AppTheme"
parent="Theme.AppCompat">
...
name="BeatBoxButton"
parent="Widget.AppCompat.Button">
name="android:background">@drawable/button_beat
_box_normal
name="android:background">@drawable/button_beat _box
часть реализации
onBindViewHolder(...)
.
Ну и как это сделать? Вы можете выдавать отдельный
асинхронный запрос на Retrofit для каждой загрузки
изображения. Однако вам придется отслеживать все объекты
Call
и управлять их жизненным циклом по отношению к
каждому контейнеру представления и самому фрагменту.
Вместо этого мы создадим фоновый поток. Этот поток будет
получать и поочередно обрабатывать запросы на загрузку, а
также предоставлять результирующее изображение для
каждого отдельного запроса по мере завершения загрузки.
Поскольку все запросы управляются фоновым потоком, без
проблем можно удалять запросы или даже останавливать
поток, вместо того чтобы управлять целой кучей отдельных
запросов.
Создание фонового потока Создайте новый класс
ThumbnailDownloader
, расширяющий
HandlerThread
. Определите для него конструктор, заглушку
реализации функции
queueThumbnail()
и переопределение
функции
quit()
, которая говорит о завершении потока (в
конце главы эта информация нам пригодится).
Листинг 25.7. Исходная версия кода потока (ThumbnailDownloader.kt) private const val TAG = "ThumbnailDownloader" class ThumbnailDownloader : HandlerThread(TAG) { private var hasQuit = false override fun quit(): Boolean { hasQuit = true return super.quit() } fun queueThumbnail(target: T, url: String) { Log.i(TAG, "Got a URL: $url") } } Классу передается один обобщенный аргумент
.
Пользователю
Thumbnail
Downloader
понадобится объект для
идентификации каждой загрузки и определения элемента
пользовательского интерфейса, который должен обновляться
после завершения загрузки. Вместо того чтобы ограничивать
пользователя одним конкретным типом объекта, мы
используем обобщенный параметр и сделаем реализацию более
гибкой.
Функция
queueThumbnail()
ожидает получить объект типа
T
, выполняющий функции идентификатора загрузки, и
String