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
Для любознательных: отмена запросов
В текущей реализации
PhotoGalleryFragment
осуществляет
к своей
ViewModel
,
Photo
GalleryViewModel
, запрос на
запуск веб-запроса на загрузку фотоданных. Если пользователь
достаточно быстро нажмет кнопку «Назад» после запуска
приложения, возможно, что веб-запрос продолжится и после
того, как пользователь закроет activity. Это не вызовет утечки
памяти, так как FlickrFetchr не содержит ссылок на
компоненты, связанные с пользовательским интерфейсом, или
на
ViewModel
.
Однако, поскольку вы игнорируете результаты, продолжение
запроса приведет к очень маленькому расходу заряда батареи и
ресурсов системы и, возможно, использованию платных
данных, если пользователь находится не в безлимитной сети.
Большого вреда нанесено не будет, так как размер данных,
которые вы получаете, очень мал.
В большинстве реальных приложений вы, скорее всего,
позволили бы запросу выполняться дальше, как и здесь. Но
вместо того чтобы игнорировать результат, вы будете где-
нибудь кэшировать его, например в базе данных.
Так как в вашей текущей реализации вы не кэшируете
результаты, вы могли бы вместо этого отменить запрос в
момент уничтожения
ViewModel
. Для этого нужно было бы
сохранить объект
Call
, представляющий собой веб-запрос.
Затем можно отменить веб-запрос, вызвав
Call.cancel()
на
сохраненные объекты вызова:
class SomeRespositoryClass {
private
lateinit
var
someCall:
Call
...
fun cancelRequestInFlight() {
if (::someCall.isInitialized) {
someCall.cancel()
}
}
}
При отмене объекта
Call
будет вызвана соответствующая
функция
Callback.onFailure(...)
. Вы можете проверить
значение
Call.isCancelled
, чтобы определить, появилась ли
из-за отмены запроса ошибка (значение
true
означает, что
запрос действительно был отменен).
Для подключения к жизненному циклу
ViewModel
, а точнее
для отмены вызовов при уничтожении
ViewModel
, нужно
переопределить функцию
ViewModel.onCleared()
. Эта
функция вызывается тогда, когда
ViewModel
вот-вот будет
уничтожен (например, когда пользователь выключает activity с
помощью кнопки «Назад»).
class SomeViewModel : ViewModel() {
private
val
someRepository
=
SomeRespositoryClass()
...
override fun onCleared() {
super.onCleared()
someRepository.cancelRequestInFlight()
}
...
}
Do'stlaringiz bilan baham: |