name="AppTheme"
parent="
Theme.AppCompat.Light.DarkActionBar
">
name="colorPrimary">@color/colorPrimary
name="colorPrimaryDark">@color/colorPrimaryDark
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
Call, t: Throwable) {
Log.e(TAG, "Failed to fetch
photos", t)
}
override fun onResponse(
call: Call,
response: Response
) {
Log.d(TAG, "Response received:
${response.body()}")
}
})
}
}
Retrofit позволяет легко соблюдать два наиболее важных
правила потоков в Android:
1. Выполнять долгосрочные операции только в фоновом
потоке, а не в основном.
2. Обновлять пользовательский интерфейс только из главного
потока, а не из фонового.
Функция
Call.enqueue(...)
выполняет веб-запрос,
находящийся в объекте
Call
. Самое главное, что запрос
выполняется в фоновом потоке. Retrofit управляет фоновым
потоком самостоятельно, и вам не нужно об этом думать.
В потоке ведется очередь задач, которые необходимо
выполнить. При вызове функции
Call.enqueue(...)
Retrofit
добавляет запрос в свою очередь задач. Вы можете вызывать
несколько запросов, и Retrofit будет обрабатывать их один за
другим до тех пор, пока очередь не станет пустой (подробнее о
создании и управлении фоновыми потоками поговорим в главе
25).
Объект
Callback
, который вы передаете в
enqueue(...)
,
позволяет определить, что вы хотите сделать после того, как
будет получен ответ на запрос. Когда запрос, выполняемый в
фоновом потоке, будет завершен, Retrofit вызовет одну из
функций обратного вызова, которую вы предоставили в
основном потоке (UI): если ответ от сервера получен,
вызывается функция
Callback.onResponse(...)
, а если нет,
то
onFailure(...)
.
Передача
Response
Retrofit в
onResponse()
содержит в
своем теле содержимое результата. Тип результата будет
соответствовать типу возвращаемого объекта, который вы
указали в соответствующей функции в интерфейсе API. В
данном случае
fetchContents()
возвращает
Call
,
поэтому
response.body()
возвращает строку.
Объект
Call
, переданный функциям
onResponse()
и
onFailure()
, — это исходный объект вызова, используемый
для инициирования запроса.
Вы можете организовать синхронное выполнение запросов с
помощью вызова
Call.execute()
. Просто убедитесь, что
выполнение происходит в фоновом, а не в основном потоке
пользовательского интерфейса. Как вы узнали из главы 11,
Android запрещает все сетевые взаимодействия в основном
потоке. Если вы попытаетесь это сделать, Android выдаст
исключение
NetworkOnMainThread
Exception
.
Do'stlaringiz bilan baham: |