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
часть
кода
из
PhotoGalleryFragment
, но убедитесь, что вставленный
результат соответствует коду в листинге 24.16.)
Листинг 24.16. Добавление функции fetchContents() во FlickrFetchr (FlickrFetchr.kt) private const val TAG = "FlickrFetchr"
class FlickrFetchr {
private val flickrApi: FlickrApi
init {
...
}
fun fetchContents(): LiveData { val responseLiveData: MutableLiveData = MutableLiveData() val flickrRequest: Call = flickrApi.fetchContents() flickrRequest.enqueue(object : Callback {
override fun onFailure(call: Call, t: Throwable) { Log.e(TAG, "Failed to fetch photos", t) } override fun onResponse( call: Call, response: Response ) { Log.d(TAG, "Response received") responseLiveData.value = response.body() } }) return responseLiveData } }
В функции
fetchContents()
вы приписываете значение
responseLiveData
пустому
объекту
MutableLiveData . Затем вы ставите в очередь веб-
запрос для получения страницы Flickr и возвращаете
responseLiveData
(до завершения запроса). После успешного
завершения результат становится публичным путем установки
значения
responseLiveData.value
. Таким образом, другие
компоненты, такие как
PhotoGalleryFragment
, могут
наблюдать
объект
LiveData
,
возвращенный
из
fetchContents()
, чтобы в конечном итоге получить
результаты веб-запроса.
Обратите
внимание,
что
возвращаемый
тип
fetchContents()
является
неизменяемым
LiveData . Вам следует избегать выставления на
публику объектов «живых» данных, если это возможно, чтобы
другие компоненты не могли изменять содержимое «живых»
данных. Данные через
LiveData
должны идти в одном
направлении.
FlickrFetchr
оборачивает большую часть сетевого кода в
PhotoGallery (сейчас обертка простая, но мы усложним ее в
следующих главах). Функция
fetchContents()
ставит в
очередь сетевой запрос и обертывает результат в
LiveData
.
Теперь другие компоненты вашего приложения, такие как
PhotoGalleryFragment
(или
ViewModel
или activity и т.д.),
могут создавать экземпляр
FlickrFetchr
и запрашивать
данные фотографии без необходимости знать что-то о Retrofit
или об источнике, из которого исходят данные.
Измените код
PhotoGalleryFragment
, чтобы использовать
FlickrFetchr
и увидеть магию в действии (листинг 24.17).