Not Running — шта је то, почетно стање животног циклуса

Аутор: IT Sectr Објављено: 2026-03-03 Време читања: 11 мин

Not Running — почетно стање животног циклуса мобилне апликације, у коме она још није покренута или је већ завршила рад. Сазнајте како систем iOS и Android управљају овим стањем, који догађаји доводе до прелаза из Not Running и како правилно обрадити покретање и завршетак апликације у Swift и Kotlin.

Главне тачке

  • Not Running — апликација није учитана у меморију и не извршава код, то је тачка улаза и излаза у животном циклусу
  • Покретање — прелаз из Not Running се дешава при додиру на икону, путем deep link-а или push обавештења
  • Завршетак — корисник затвара апликацију превлачењем, систем је истоварује при недостатку меморије или долази до краша
  • Хладни старт — апликација стартује од нуле, сви објекти се поново креирају, стање се не обнавља из кеша
  • Топли старт — апликација је била у Suspended и враћа се у Active без потпуне иницијализације

Not Running — шта је ово стање

Not Running — је основно стање животног циклуса мобилне апликације, у којем она није учитана у RAM меморију уређаја и не троши системске ресурсе. У iOS и Android ово стање значи потпуно одсуство процеса и нити повезаних са апликацијом. Корисник види икону апликације на радној површини, али сама апликација није активна и не налази се на листи недавних.

Када корисник додирне икону, систем креира нови процес, учитава извршни код у меморију и иницијализује све потребне структуре података. Овај процес се назива хладни старт (cold start) и највише захтева ресурсе у погледу времена учитавања.

Систем може преместити апликацију у Not Running из било ког другог стања. Ако се апликација налази у позадини (Background) или је суспендована (Suspended), оперативни систем има право да је истовари при недостатку RAM меморије за приоритетније задатке — на пример, за активну апликацију у предњем плану.

Програмер мора имати у виду да апликација може бити завршена од стране система у било ком тренутку, када се налази у позадини. То значи да сви несачувани подаци могу бити изгубљени. Због тога је критично важно чувати стање у складиштима кључ-вредност (UserDefaults, SharedPreferences) или у локалној бази података при прелазима из Active у Background.

Како систем одређује коју апликацију да истовари

iOS користи приоритете на основу тренутног стања апликације: Active има највећи приоритет, затим Inactive, Background, Suspended и на крају Not Running — минимални приоритет. Android користи сличну хијерархију процеса: Foreground процес има приоритет OOM_ADJ = 0, Visible процес = 100, Service процес = 200, Background процес = 300, Empty процес = 400. Што је вредност већа, већа је вероватноћа да ће процес бити завршен при недостатку меморије.

ПлатформаСтањеПриоритет истовараОпис
iOSNot RunningНајвећиАпликација није учитана — системски ресурс се не троши
iOSSuspendedВисокАпликација у меморији, али се код не извршава — прва мета за истовар
iOSBackgroundСредњиАпликација извршава позадински задатак — истоварује се након истека времена
iOSActiveНизакАктивна апликација — истоварује се само при критичном недостатку меморије
AndroidEmpty ProcessНајвећиПроцес без активних компоненти — први се уклања
AndroidBackground ProcessВисокПозадински процес без видљивог Activity
AndroidForeground ServiceНизакСервис са обавештењем — ретко се завршава
AndroidForeground ProcessМинималанАктивно Activity — завршава се последње

Хладни и топли старт апликације

Хладни старт (cold start) се дешава када апликација пређе из Not Running директно у Active. Систем креира нови процес, учитава класе, иницијализује статичка поља, креира главну нит и покреће UI оквир. На iOS-у то значи позив application(_:didFinishLaunchingWithOptions:), на Android-у — позив Application.onCreate() и Activity.onCreate(). Време хладног старта може бити од 200 ms до неколико секунди у зависности од сложености апликације.

Топли старт (warm start или hot start) — апликација је била у стању Suspended и враћа се у рад без потпуног поновног учитавања. Систем обнавља последњи UI стек из меморије, а корисник наставља рад са истог места. Топли старт је значајно бржи од хладног, јер је већи део кода већ учитан у меморију. На iOS-у топли старт не позива application(_:didFinishLaunchingWithOptions:), само applicationWillEnterForeground и applicationDidBecomeActive.

Разлика између хладног и топлог старта је критична за корисничко искуство. При хладном старту, програмер мора да обезбеди да се покретање догоди што је брже могуће — лења иницијализација модула, одложено учитавање тешких ресурса, минимизација рада у главној нити при старту. Google препоручује хладни старт не дужи од 500 ms, Apple — не дужи од 400 ms за iOS.

kotlin
// Мерење времена хладног старта на Android-у
class App : Application() {
    private var startTime: Long = 0L

    override fun onCreate() {
        super.onCreate()
        startTime = System.currentTimeMillis()
    }

    fun getStartupTime(): Long {
        return System.currentTimeMillis() - startTime
    }
}

// Покретање Activity са лењом иницијализацијом
class MainActivity : AppCompatActivity() {
    private val viewModel: MainViewModel by lazy {
        ViewModelProvider(this).get(MainViewModel::class.java)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // Само неопходни минимум за први кадар
        setupNavigation()
    }

    override fun onPostCreate(savedInstanceState: Bundle?) {
        super.onPostCreate(savedInstanceState)
        // Тешка иницијализација након рендеровања
        initializeHeavyModules()
    }
}

Пример приказује мерење времена хладног старта на Android-у. Application.onCreate() се позива при прелазу из Not Running у Active. Временска ознака се бележи при покретању процеса. Activity користи лењу иницијализацију преко lazy-делегата да не би блокирао први кадар. onPostCreate је оптимално место за иницијализацију тешких модула, јер је UI већ исцртан.

Not Running у iOS: Swift и AppDelegate

У iOS-у Not Running се управља преко делегата UIApplicationDelegate. Кључне методе: application(_:didFinishLaunchingWithOptions:) се позива након хладног старта, applicationWillTerminate(_:) се позива пре завршетка апликације од стране корисника. Систем може завршити апликацију без позивања applicationWillTerminate — на пример, при хитном завршетку или истовару меморије. iOS не гарантује позивање ове методе, зато податке треба чувати у applicationDidEnterBackground.

Сценарији преласка у Not Running на iOS-у

Корисник може ручно завршити апликацију превлачењем у App Switcher-у. Систем може истоварити апликацију из меморије у позадини. Апликација може хитно завршити (crash). У свим случајевима, сви објекти креирани током покретања се уништавају. Стање које није сачувано се неповратно губи. У iOS 13+ за чување стања препоручује се коришћење NSUserActivity или механизма state restoration кроз UIApplication.stateRestorationIdentifier.

swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    // Хладни старт: апликација је прешла из Not Running
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        // Иницијализација минималног скупа услуга
        setupAnalytics()
        configureAppearance()
        return true
    }

    // Апликација завршава рад — само ручно затварање
    func applicationWillTerminate(
        _ application: UIApplication
    ) {
        saveCriticalData()
    }

    // Чување података пре одласка у позадину
    func applicationDidEnterBackground(
        _ application: UIApplication
    ) {
        saveApplicationState()
    }

    private func saveCriticalData() {
        UserDefaults.standard.synchronize()
    }

    private func saveApplicationState() {
        let state = ["lastScreen": "main", "timestamp": Date()]
        try? NSKeyedArchiver.archivedData(
            withRootObject: state,
            requiringSecureCoding: true
        )
    }
}

Код приказује исправну обраду Not Running на iOS-у. applicationWillTerminate се позива само при ручном завршетку од стране корисника. Чување критичних података је дуплирано у applicationDidEnterBackground, јер је ова метода гарантовано позвана пре одласка у позадину. State restoration омогућава чување UI стека за касније обнављање при хладном старту.

Not Running у Android: Kotlin и процес

У Android-у Not Running значи да процес апликације не постоји. Linux систем на коме се заснива Android управља процесима кроз механизам Zygote. При покретању апликације, Zygote форкује нови процес, учитава Dalvik/ART и позива Application.onCreate(). У Android-у не постоји директни аналог applicationWillTerminate — систем може завршити процес у било ком тренутку без упозорења.

Животни циклус процеса Android

Када се Activity позове први пут, систем креира процес, Application и Activity кроз ланац onCreate → onStart → onResume. Ако корисник притисне Back, Activity се уништава (onDestroy), а процес може бити завршен од стране система. Кључна разлика у односу на iOS: у Android-у процес може наставити да постоји чак и без активних Activity-ја — на пример, ако ради Foreground Service или постоји активан BroadcastReceiver.

kotlin
// Обрада Not Running кроз SavedStateHandle у ViewModel
class MainViewModel(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    companion object {
        private const val KEY_LAST_SCREEN = "last_screen"
        private const val KEY_USER_DATA = "user_data"
    }

    fun saveCurrentState(screen: String, data: String) {
        savedStateHandle[KEY_LAST_SCREEN] = screen
        savedStateHandle[KEY_USER_DATA] = data
    }

    fun restoreState(): AppState? {
        val screen = savedStateHandle.get<String>(KEY_LAST_SCREEN)
        val data = savedStateHandle.get<String>(KEY_USER_DATA)
        return if (screen != null && data != null) {
            AppState(screen, data)
        } else null
    }
}

// Application — први повратни позив након Not Running
class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        initCrashReporter()
        initDependencyInjection()
    }
}

SavedStateHandle — компонента Android Architecture Components која аутоматски чува стање при преласку у Not Running и обнавља га при хладном старту. ViewModel креиран кроз ViewModelProvider преживљава ротацију екрана и уништавање Activity. При завршетку процеса, подаци из SavedStateHandle се серијализују у Bundle и чувају у saved instance state.

Разлози преласка у Not Running

Not Running наступа из неколико разлога. Корисник ручно затвара апликацију. Систем истоварује апликацију при недостатку меморије. Апликација хитно завршава са изузетком. На Android-у систем може завршити процес при масовном ажурирању апликација или ресетовању уређаја. iOS може завршити апликацију при истеку времена позадинског задатка (обично 30 секунди).

РазлогiOSAndroidМогућност превенције
Ручно затварање од стране корисникаПревлачење у App Switcher-уПревлачење из Recents-аНе — радња корисника
Недостатак меморијеАктивирање memory warning-аonTrimMemory / LMKДелимично — оптимизација меморије
Краш апликацијеNSException / сигналUncaughtException / ANRДа — обрада грешака и crash-reporting
Истек времена позадинског задатка30 сек за Background task10 мин за JobSchedulerДа — правилно планирање задатака
Ресетовање ОСПозив applicationWillTerminateBroadcast ACTION_SHUTDOWNНе — системски догађај
Ажурирање апликацијеНе дешава се (iOS Sandbox)Процес се завршава при APK ажурирањуНе — системско ажурирање

Како дијагностиковати прелазак у Not Running

За iOS користите конзолно логирање у applicationWillTerminate и applicationDidFinishLaunching. Додајте заставицу у UserDefaults при сваком покретању — ако при следећем старту заставица недостаје, апликација је завршена некоректно. На Android-у користите ActivityManager.isBackgroundRestricted() да проверите да ли апликација може да покреће позадинске задатке. Такође пратите onTrimMemory(TRIM_MEMORY_COMPLETE) — то је сигнал да ће процес бити завршен.

Најбоље праксе рада са Not Running

Прво правило — никада не претпостављајте да ће applicationWillTerminate или onDestroy бити позвани. Чувајте критично важне податке при сваком прелазу из Active у Background. Користите складишта кључ-вредност за једноставна подешавања и SQLite/Room за структуриране податке.

Друго правило — мерите време хладног старта и оптимизујте га. Лења иницијализација, минимизација рада у главној нити, претходно учитавање ресурса, коришћење SplashScreen API-ја — све то побољшава перцепцију времена покретања. Google препоручује хладни старт мањи од 200 ms за одличан UX.

Треће правило — имплементирајте State Restoration. На iOS-у користите UIApplication.stateRestorationIdentifier и NSUserActivity. На Android-у користите SavedStateHandle у ViewModel-у у комбинацији са onSaveInstanceState. Ово ће омогућити кориснику да настави рад са истог места након поновног покретања апликације.

Четврто правило — обрађујте launchOptions и Intent са којима је апликација покренута након Not Running. Deep link-ови, push обавештења, универзални линкови — сви се преносе кроз параметре покретања. Програмер мора правилно да извуче ове податке и усмери корисника на одговарајући екран.

swift
// Обрада deep link-а након хладног старта
func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    // Провера да ли је стигло обавештење
    if let notification = launchOptions?[.remoteNotification] as? [String: Any] {
        handleNotification(notification)
    }
    // Провера deep link-а
    if let url = launchOptions?[.url] as? URL {
        handleDeepLink(url)
    }
    return true
}

private func handleDeepLink(_ url: URL) {
    guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
          let screenId = components.queryItems?.first(where: { $0.name == "screen" })?.value
    else { return }
    openScreen(screenId)
}

Код приказује обраду параметара покретања при хладном старту на iOS-у. launchOptions садржи податке са којима је систем покренуо апликацију. Обавештења, deep link-ови и универзални линкови се преносе кроз овај речник. Програмер мора правилно да обради све могуће сценарије покретања како би обезбедио беспрекорно корисничко искуство.

Често постављана питања

Шта се дешава са подацима при преласку у Not Running?

Подаци који су сачувани у трајном складишту (UserDefaults, Core Data, SharedPreferences, Room) се чувају. Подаци у RAM меморији — променљиве, кеш, стање ViewModel без SavedStateHandle — се неповратно губе. Зато је критично важно чувати стање апликације при сваком преласку у позадину.

Како разликовати хладни старт од топлог на iOS-у?

При хладном старту се позива application(_:didFinishLaunchingWithOptions:). При топлом старту (повратак из Suspended) ова метода се не позива — активирају се само applicationWillEnterForeground и applicationDidBecomeActive. Ако треба да извршите радњу само при хладном старту, поставите заставицу у didFinishLaunchingWithOptions.

Може ли Android апликација бити у Not Running са активним Service-ом?

Да. Foreground Service са сталним обавештењем спречава завршетак процеса од стране система, чак и ако су сва Activity уништена. Background Service (startService без foreground) може бити заустављен од стране система у било ком тренутку. Радни Service значи да процес постоји и то више није Not Running.

Како емулирати Not Running на симулатору?

На iOS симулатору завршите апликацију кроз App Switcher (Cmd+Shift+H двапут, превуците нагоре). На Android емулатору користите adb shell am force-stop com.example.app или дугме Stop у Logcat-у. Затим поново покрените апликацију — ово ће бити чист хладни старт из Not Running.

Шта је kill-switch у контексту Not Running?

Kill-switch — серверска команда за хитно завршавање апликације. Користи се у банкарским и корпоративним апликацијама за даљинско блокирање приступа. Ако је апликација примила kill команду, при следећем хладном старту блокира UI и захтева поновну ауторизацију. На iOS-у kill-switch се имплементира кроз remote notifications са заставицом блокирања.

Закључак

  • Not Running — почетно и крајње стање животног циклуса, апликација није учитана у меморију и не извршава код
  • Хладни старт — потпуно поновно учитавање апликације из Not Running, захтева иницијализацију свих компоненти од нуле
  • Топли старт — повратак из Suspended, не позива didFinishLaunchingWithOptions нити Application.onCreate
  • Чување података — критично важно при преласку у Background, јер Not Running може наступити у било ком тренутку
  • iOS — applicationWillTerminate није гарантован, стање се чува кроз UserDefaults или state restoration
  • Android — процес може бити завршен у било ком тренутку, SavedStateHandle у ViewModel чува стање аутоматски
  • Оптимизација старта — лења иницијализација, минималан рад у main thread-у, SplashScreen API за брзи први кадар

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође