onStart — е метод от жизнения цикъл на Android, който се извиква, когато Activity или Fragment стават видими за потребителя. В този момент екранът се появява на дисплея на устройството, но все още не може да взаимодейства с потребителя — фокусът за въвеждане липсва до извикването на onResume. Методът onStart е идеален за регистриране на системни слушатели, свързване към услуги за геолокация и стартиране на анимации, които трябва да работят, докато компонентът е видим на екрана. Повече за пълния жизнен цикъл на Activity прочетете в статията Activity Lifecycle.
Основни неща
onStart — вторият метод от жизнения цикъл на Activity, който се извиква от системата след onCreate (или след onRestart при връщане от спряно състояние). В момента на извикване на onStart, Activity или Fragment стават видими на екрана. Потребителят вижда интерфейса, но екранът все още не е готов за взаимодействие — фокусът за въвеждане ще се появи едва след onResume.
Методът onStart влиза в „видимия живот" (visible lifetime) на Activity — интервалът между onStart и onStop. През този период Activity може да бъде частично закрита от други прозорци (например от прозрачно Activity или диалогов прозорец), но нейният потребителски интерфейс остава видим. Това различава видимия живот от „живота на преден план" (onResume — onPause), когато Activity има пълен фокус за въвеждане.
Разбирането на тази тристепенна йерархия е критично важно за правилното разпределение на кода. onCreate — еднократна инициализация, onStart — свързване на видими ресурси, onResume — монополен достъп до ексклузивни ресурси. Разработчик, който бърка тези нива, рискува да създаде изтичане на памет или неправилно поведение на приложението при превключване между екрани.
В Activity методът onStart се извиква всеки път, когато екранът се появи на дисплея — както при първото стартиране (след onCreate), така и при връщане от фонов режим (след onRestart). За разлика от onCreate, onStart може да се извиква многократно през живота на инстанцията на Activity, затова тук се поставя код, който трябва да се изпълнява всеки път при появяване на екрана.
class DashboardActivity : AppCompatActivity() {
private val connectivityReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val isConnected = ... // проверка на ConnectivityManager
binding?.statusIndicator?.setColor(
if (isConnected) Color.GREEN else Color.RED
)
}
}
override fun onStart() {
super.onStart()
registerReceiver(
connectivityReceiver,
IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
)
SensorManager.getInstance().registerStepCounter()
}
override fun onStop() {
unregisterReceiver(connectivityReceiver)
SensorManager.getInstance().unregisterStepCounter()
super.onStop()
}
}
Ключово правило: всички ресурси, свързани в onStart, трябва да бъдат освободени в onStop. Това гарантира, че когато Activity е скрита от екрана, тя не консумира батерия, не слуша системни събития и не заема памет. Android Studio съдържа lint правила, предупреждаващи за регистриране на BroadcastReceiver без съответното отписване.
onStart във Fragment е тясно свързан с жизнения цикъл на контейнерното Activity. Fragment получава извикването onStart, след като Activity, в което се намира, е получило onStart. Въпреки това, ако Fragment е добавен в отложен режим (FragmentTransaction.commit() без addToBackStack), onStart може да бъде извикан със закъснение.
class MapFragment : Fragment() {
private var mapView: MapView? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
mapView = MapView(requireContext())
return mapView!!
}
override fun onStart() {
super.onStart()
mapView?.onStart()
LocationService.connect(requireContext())
}
override fun onStop() {
mapView?.onStop()
LocationService.disconnect()
super.onStop()
}
}
Специфика на Fragment.onStart: ако Fragment се намира в ViewPager с offscreenPageLimit = 1, съседните фрагменти също ще получат onStart, преди да станат видими. Това може да доведе до преждевременна регистрация на слушатели. За такива случаи се използва методът setUserVisibleHint() или проверка на isVisible вътре в onStart, за да се регистрират слушатели само за действително видими фрагменти.
Основната разлика между onStart и onResume — нивото на активност на екрана. onStart сигнализира, че Activity е видимо на екрана, но не е задължително да е на преден план. onResume сигнализира, че Activity е на преден план и има фокус за въвеждане. Разликата се демонстрира с примера на диалогов прозорец: когато над Activity се появи Dialog, Activity губи onResume (извиква се onPause), но остава видимо — onStart/onStop не се извикват.
Таблицата с разликите ясно показва в кои сценарии се извиква всеки метод:
| Сценарий | onStart | onResume |
|---|---|---|
| Стартиране на приложението | Извиква се | Извиква се |
| Над Activity е отворен Dialog | Не се извиква | onPause (загуба на фокус) |
| Натискане на бутона „Начало" | onStop (скрито) | onPause → onStop |
| Връщане от „Последни" | onStart (видимо) | onResume (фокус) |
| Завъртане на екрана | onCreate → onStart | → onResume |
| Входящо повикване | onStop (скрито) | onPause → onStop |
Тази таблица помага на разработчика да реши в кой метод да постави конкретния код. Например, ако приложението трябва да постави на пауза възпроизвеждането на видео при всяко закриване на екрана (дори и с диалог), кодът се поставя в onPause. Ако видеото трябва да спира само при пълно скриване на екрана — кодът се поставя в onStop.
onStart — оптималното място за регистриране на слушатели, които трябва да работят само докато Activity е видимо на екрана. Това се отнася за три основни типа системни компоненти: BroadcastReceiver за системни събития, LocationListener за геолокация и SensorListener за сензори на устройството.
BroadcastReceiver се регистрира динамично чрез Context.registerReceiver() в onStart и се отписва в onStop чрез unregisterReceiver(). Динамичната регистрация е за предпочитане пред статичната (в манифеста), тъй като ограничава живота на приемника до периода на видимост на Activity — приложението не се събужда от системни broadcast съобщения, когато Activity е скрито.
private val batteryReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
binding?.batteryText?.text = "$level%"
}
}
override fun onStart() {
super.onStart()
registerReceiver(batteryReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
}
override fun onStop() {
unregisterReceiver(batteryReceiver)
super.onStop()
}
Геолокацията и сензорите — ресурсоемки операции. Заявката за GPS актуализации в onStart и отмяната в onStop гарантира, че приложението не консумира батерия, когато екранът е скрит. За прецизно настройване се използва requestLocationUpdates с минимален интервал и разстояние — например 10 секунди и 10 метра, което дава оптимален баланс между точност и консумация на енергия.
Стартирането на анимации в onStart, а не в onCreate, гарантира, че анимацията тръгва всеки път при появяване на екрана. Ако стартирате анимация в onCreate, тя ще работи само при първото създаване на Activity, но не и при връщане от фонов режим. onStart се извиква всеки път, когато Activity стане видимо, което го прави идеално място за стартиране на циклични анимации и преходи.
private lateinit var pulseAnimator: ValueAnimator
override fun onStart() {
super.onStart()
pulseAnimator.start()
binding?.loadingIndicator?.animate()?.alpha(1f)?.start()
}
override fun onStop() {
pulseAnimator.cancel()
binding?.loadingIndicator?.animate()?.cancel()
super.onStop()
}
За анимации, използващи ObjectAnimator или ValueAnimator, е важно да се извиква cancel() в onStop. Ако анимацията продължава да работи след скриване на Activity, тя безполезно консумира GPU и CPU ресурси, което намалява производителността на устройството и ускорява разреждането на батерията. Android Studio Profiler (графика на GPU) позволява проследяване на активни анимации и откриване на изтичания.
Правилото за двойката onStart/onStop е приложимо и за работа с камера за преглед (CameraX). Отварянето на камерата в onStart и затварянето в onStop гарантира, че камерата не е блокирана за други приложения, когато вашето приложение не е видимо на екрана. Нарушаването на това правило е една от честите причини за отрицателни отзиви в Google Play.
Често задавани въпроси
onStart — за слушатели, които трябва да работят, докато екранът е видим (BroadcastReceiver, LocationListener, SensorListener). onResume — за ресурси, изискващи монополен достъп (камера, видеозаснемане, разпознаване на реч). Слушателите на системни събития не изискват монополен достъп и могат да работят при частично закриване — те се регистрират в onStart. Камерата трябва да е активна само при пълен фокус — отваря се в onResume.
onStart винаги се извиква, ако Activity преминава във видимо състояние. Единственият сценарий без onStart — Activity се създава и веднага се прекратява (например поради грешка в onCreate). В този случай след onCreate веднага следва onDestroy. Но това е авариен сценарий, който не трябва да присъства в правилно написан код.
Да, onStart може да не получи onResume, ако над Activity веднага се отвори друго Activity или прозрачен прозорец. Например, ако след onCreate се стартира екран за автентикация (Activity A → Activity B), в Activity A onStart се извиква, но onResume не — то получава директно onPause → onStop при закриване от екран B.
onStart може да бъде извикан многократно през живота на инстанцията на Activity. Всеки път, когато Activity преминава от скрито състояние (onStop) във видимо, се извиква onStart. На практика, при активно използване на приложението, onStart може да се извиква десетки или стотици пъти по време на сесия.
Зареждането на данни в onStart е оправдано, ако данните трябва да се актуализират всеки път при появяване на екрана. Например, новинарски поток или списък с известия. Но зареждането трябва да бъде асинхронно — чрез корутини с lifecycleScope, за да не блокира UI нишката. За данни, които не се променят между появяванията на екрана, достатъчно е да се заредят веднъж в onCreate.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също