В чем разница между Activity Context и Application Context?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
В чем разница между Activity Context и Application Context
Основное отличие
Activity Context привязан к конкретной Activity, существует столько же, сколько существует Activity. Application Context один на все приложение и живет столько же, сколько живет приложение.
// Activity Context
val activityContext: Context = this // В Activity
// Application Context
val appContext: Context = getApplicationContext() // или this в Application
val appContext2 = this@Activity.applicationContext
1. Жизненный цикл
Activity Context:
- Создается при создании Activity
- Уничтожается при уничтожении Activity
- Привязан к UI
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val context: Context = this // Activity Context
// При finish() этот контекст будет уничтожен
}
}
Application Context:
- Создается при запуске приложения
- Живет до завершения процесса
- Единственный на все время жизни app
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
val context: Context = this // Application Context
// Живет столько же, сколько живет приложение
}
}
2. Использование в разных ситуациях
Когда использовать Activity Context
✅ UI операции, привязанные к Activity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Dialog привязан к Activity
AlertDialog.Builder(this) // Activity Context!
.setTitle("Подтверждение")
.setMessage("Вы уверены?")
.show()
}
}
✅ Toast, View, LayoutInflater:
// Toast привязан к Activity и будет скрыт при её уничтожении
Toast.makeText(this, "Сообщение", Toast.LENGTH_SHORT).show()
// LayoutInflater связан с Activity
val view = LayoutInflater.from(this).inflate(R.layout.my_layout, null)
✅ Animations, transitions:
val animator = ObjectAnimator.ofInt(this, "backgroundColor", Color.RED)
// Привязан к Activity
Когда использовать Application Context
✅ Синглтоны, которые живут долго:
class DatabaseManager private constructor(context: Context) {
private val appContext = context.applicationContext // Берем Application Context!
companion object {
@Volatile
private var instance: DatabaseManager? = null
fun getInstance(context: Context) =
instance ?: synchronized(this) {
instance ?: DatabaseManager(context)
}
}
// Database инициализируется один раз и живет до конца app
private val database = Room.databaseBuilder(
appContext, // НЕ Activity Context!
AppDatabase::class.java,
"database.db"
).build()
}
✅ Шаредпрефернцесы:
class PreferenceManager(context: Context) {
private val appContext = context.applicationContext
private val prefs = appContext.getSharedPreferences(
"my_prefs",
Context.MODE_PRIVATE
)
fun saveUser(name: String) {
prefs.edit().putString("user_name", name).apply()
}
}
✅ Event Bus, Broadcast Receivers:
class EventBus(context: Context) {
private val appContext = context.applicationContext
fun registerReceiver(receiver: BroadcastReceiver, filter: IntentFilter) {
appContext.registerReceiver(receiver, filter) // Application Context!
}
}
✅ Network requests, API client:
class ApiClient(context: Context) {
private val appContext = context.applicationContext
private val httpClient = OkHttpClient()
suspend fun getUsers(): List<User> {
// HTTP запрос не привязан к Activity
return httpClient.newCall(request).execute()
}
}
3. Проблемы с неправильным использованием
❌ НЕПРАВИЛЬНО: Activity Context в Singleton
class BadRepository(context: Context) {
// УТЕЧКА ПАМЯТИ!
// Activity Context живет дольше Activity и держит её в памяти
private val context = context // Activity Context
fun getData() {
// Activity давно уничтожена, но её Context все еще в памяти
}
}
Почему: Activity Context держит ссылку на всю Activity, включая все View'ы. Если Context живет в Singleton, то Activity никогда не будет garbage collected.
✅ ПРАВИЛЬНО: Application Context в Singleton
class GoodRepository(context: Context) {
// ОК, Application Context живет столько же, сколько app
private val appContext = context.applicationContext
fun getData() {
// Нет утечек памяти
}
}
4. Сравнительная таблица
| Характеристика | Activity Context | Application Context |
|---|---|---|
| Жизненный цикл | Равен Activity | Равен приложению |
| Использование для UI | ✅ Да | ❌ Нет (нет доступа к Activity) |
| AlertDialog | ✅ Работает | ❌ Ошибка |
| Toast | ✅ Работает | ⚠️ Работает, но странно |
| Dialogs | ✅ Работает | ❌ Ошибка |
| Database | ⚠️ Работает, но утечка | ✅ Идеально |
| SharedPreferences | ⚠️ Работает, но утечка | ✅ Идеально |
| Service запуск | ⚠️ Работает, но утечка | ✅ Идеально |
| BroadcastReceiver | ⚠️ Работает, но утечка | ✅ Идеально |
5. Практический пример: правильная архитектура
// Application класс - создает глобальные сервисы
@HiltAndroidApp
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
// Инициализируем Hilt, логирование и т.д.
}
}
// Module для инъекции зависимостей
@Module
@InstallIn(SingletonComponent::class)
object RepositoryModule {
@Provides
@Singleton
fun provideRepository(
@ApplicationContext context: Context // Application Context!
): UserRepository {
return UserRepository(context)
}
}
// Repository использует Application Context
class UserRepository(context: Context) {
private val appContext = context.applicationContext
private val database = Room.databaseBuilder(
appContext,
AppDatabase::class.java,
"database.db"
).build()
}
// Activity использует Repository и свой Context для UI
class MainActivity : AppCompatActivity() {
@Inject
lateinit var repository: UserRepository
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Для UI используем Activity Context (this)
AlertDialog.Builder(this) // Activity Context!
.setTitle("Загрузка")
.show()
// Для долгоживущих операций используем Repository
lifecycleScope.launch {
val users = repository.getUsers() // Использует Application Context
}
}
}
Итог
Activity Context:
- Для UI операций (Dialog, Toast, LayoutInflater)
- Не используй в Singleton'ах и сервисах
- Убивается вместе с Activity
Application Context:
- Для сервисов, Database, SharedPreferences
- Используй в Singleton'ах и долгоживущих объектах
- Живет столько же, сколько приложение
Золотое правило: если объект будет жить дольше Activity — используй Application Context, иначе получишь утечку памяти!