You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 10-android-sdk-deep.md
+41Lines changed: 41 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -87,6 +87,47 @@ class App : Application() {
87
87
В Compose внутри composable доступен `LocalContext.current` — как правило это activity context,
88
88
и его действует то же правило: не сохранять в долгоживущих объектах.
89
89
90
+
## 2.2. Какие операции требуют какой `Context`
91
+
92
+
Большинство методов (`getString`, `getSystemService`, `openFileInput`, `getSharedPreferences`,
93
+
`ContentResolver`, `startService`) объявлены уже у базового `Context`. Вопрос не в том, можно ли
94
+
вызвать метод, а достаточно ли у конкретного экземпляра lifetime, theme, configuration и window token
95
+
для желаемого результата.
96
+
97
+
| Операция | Подходящий Context | Важное ограничение |
98
+
| --- | --- | --- |
99
+
| БД, DataStore, SharedPreferences, файлы, `ContentResolver`, WorkManager, singleton SDK |`applicationContext`| Хранить только application context в long-lived object; Activity здесь не нужна и создаст утечку. |
100
+
| Ресурсы без UI (`getString`, raw resource), `PackageManager`, большинство system services | обычно `applicationContext`| Ресурсы application context не отражают configuration конкретного окна: например, локальный override locale, night mode или display size Activity. |
101
+
| Инфляция layout, themed attribute (`?attr/colorPrimary`), `ContextThemeWrapper`|`Activity` или тематизированный `ContextThemeWrapper`| Метод `LayoutInflater.from(context)` доступен с любым Context, но application context часто даст базовую/не ту тему. |
102
+
| Обычный `Dialog`, `PopupWindow`, привязанный к экрану UI |`Activity`| Нужны theme и window token текущего окна. Application context не подходит для обычного dialog. |
103
+
| Runtime permission, `ActivityResultLauncher`, системный picker с result callback |`Activity` / `Fragment`|`requestPermissions` и регистрация Activity Result требуют lifecycle/UI owner, а не просто Context. |
104
+
| Открыть экран через `startActivity`|`Activity`; из другого Context тоже возможно | У `applicationContext`/`Service` обязателен `FLAG_ACTIVITY_NEW_TASK`; background activity launch ограничен платформой. |
105
+
|`startService`, `bindService`, `startForegroundService`| любой `Context`| Для долгой работы в фоне действуют background execution limits; foreground service должен быстро вызвать `startForeground`, а durable work обычно принадлежит WorkManager. |
106
+
| Показать `Toast`, создать notification/`NotificationManager`|`applicationContext`| Не держит экран и безопасен для долгоживущего кода; notification tap открывает UI через `PendingIntent`, а не прямой reference на Activity. |
107
+
| Зарегистрировать receiver на время экрана |`Activity`/`Fragment` context и симметричный unregister | Регистрацию снимают с тем же lifetime; receiver, созданный в `onReceive`, не должен хранить его `context` или делать долгую работу после возврата. |
108
+
| Окно поверх других приложений | application/window context + `TYPE_APPLICATION_OVERLAY`| Требуется `SYSTEM_ALERT_WINDOW`; это не замена dialog и имеет отдельные policy/UX ограничения. |
109
+
110
+
Практическое правило: передавайте вниз самый узкий Context, который действительно нужен. Repository обычно
111
+
получает `applicationContext`; UI-компонент получает `Activity` не как поле, а только на время операции.
112
+
Если API нужен лишь для строки или system service, принимайте конкретную dependency (`Resources`,
113
+
`NotificationManager`, `ContentResolver`), а не весь `Context` — это уменьшает связность и риск утечки.
114
+
115
+
```kotlin
116
+
classImageCache(context:Context) {
117
+
privateval appContext = context.applicationContext // cache живёт дольше Activity
118
+
}
119
+
120
+
funopenDetails(context:Context, id:String) {
121
+
val intent =Intent(context, DetailActivity::class.java).putExtra("id", id)
122
+
if (context !isActivity) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
123
+
context.startActivity(intent)
124
+
}
125
+
```
126
+
127
+
`context.applicationContext` может быть `null` у редких custom/wrapper contexts; в application-scoped
128
+
зависимости лучше инъецировать именно `Application` или заранее проверенный app context, а не silently
0 commit comments