Какие знаешь объекты, которые могут пережить Activity?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Объекты, переживающие уничтожение Activity
В контексте жизненного цикла Android Activity, существует несколько категорий объектов, которые могут сохранять своё состояние или существовать дольше, чем сама Activity. Это критически важно для поддержания данных при пересоздании Activity (например, при повороте экрана) или для выполнения фоновых операций.
Основные категории
1. Объекты, связанные с Application Context
Любой объект, привязанный к Application Context (контексту приложения), будет существовать всё время жизни приложения.
class MyApp : Application() {
val globalCache = mutableMapOf<String, Any>()
}
// Доступ из любой Activity
val app = applicationContext as MyApp
app.globalCache["key"] = data
- Application-класс: Singleton, существующий от запуска до завершения процесса.
- Статические поля (static): Хранятся в PermGen/Metaspace, живут пока загружен класс.
- Объекты в Dependency Injection контейнерах (Dagger, Koin) с областью видимости Application.
2. Архитектурные компоненты и ViewModel
ViewModel из Android Jetpack специально разработан для переживания изменений конфигурации.
class UserViewModel : ViewModel() {
private val _userLiveData = MutableLiveData<User>()
val userLiveData: LiveData<User> = _userLiveData
fun loadUser() { /* ... */ }
}
// В Activity
val viewModel = ViewModelProvider(this).get(UserViewModel::class.java)
ViewModel сохраняется в ViewModelStore до окончательного уничтожения Activity (не при изменении конфигурации). Однако он НЕ переживает завершение процесса системой.
3. Сохранённое состояние (Saved State)
Объекты, сохранённые через механизмы сохранения состояния:
- onSaveInstanceState(Bundle) - для небольших данных
- SavedStateHandle в ViewModel
class SavedStateViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {
var userData: String?
get() = savedStateHandle.get("user_key")
set(value) = savedStateHandle.set("user_key", value)
}
4. Фоновые операции и WorkManager
- Coroutine Scope с жизненным циклом приложения:
class MyActivity : AppCompatActivity() {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
override fun onDestroy() {
super.onDestroy()
// Не отменяем корутины автоматически - они переживут Activity
// scope.cancel() // нужно вызывать вручную при необходимости
}
}
- WorkManager задачи: выполняются системой вне зависимости от жизненного цикла UI.
- Service (особенно ForegroundService): работают в фоне.
- AlarmManager и BroadcastReceiver с зарегистрированными в манифесте intent-фильтрами.
5. Внешние ресурсы и синглтоны
- Базы данных (Room, SQLite): данные сохраняются на диске.
- SharedPreferences: хранилище ключ-значение.
- Файлы во внутреннем или внешнем хранилище.
- Объекты в нативном коде (JNI): управляются вручную.
- Статические коллекции (опасно! могут вызывать утечки памяти):
public class DataHolder {
public static List<Data> cache = new ArrayList<>(); // Живёт вечно
}
6. Ссылки на контекст Activity (опасный случай)
Объекты, содержащие явные ссылки на Activity Context, могут пережить Activity только при утечке памяти:
object LeakySingleton {
var leakedContext: Context? = null // Утечка если передать Activity context!
}
Важные предостережения
-
Утечки памяти - самые опасные объекты, которые переживают Activity не по дизайну, а из-за ошибок:
- Нестатичные внутренние классы с сильной ссылкой на внешний класс
- Хранение View или Context в статических полях
- Неотменённые колбэки или слушатели
-
Используйте правильные контексты:
// ПЛОХО - может вызвать утечку MyManager.init(this) // где this - Activity context // ХОРОШО MyManager.init(applicationContext) -
Очистка ресурсов - объекты, переживающие Activity, требуют ручного управления:
override fun onDestroy() { super.onDestroy() // Отписываемся от глобальных событий EventBus.getDefault().unregister(this) // Очищаем ссылки callbackHolder.removeCallbacks(this) }
Рекомендации по проектированию
- Используйте ViewModel для данных UI, связанных с жизненным циклом экрана
- Храните персистентные данные в Repository с доступом к БД или сети
- Для глобального состояния используйте Application-скоупированные объекты DI
- Всегда проверяйте, не создаёте ли вы непреднамеренных долгоживущих объектов
- Для фоновых задач применяйте Coroutines с правильным Scope или WorkManager
Правильное понимание того, какие объекты переживают Activity, позволяет создавать отзывчивые приложения без утечек памяти, с корректным восстановлением состояния пользовательского интерфейса.