Not Running — qu’est-ce que c’est, l’état initial du cycle de vie

Auteur : IT Sectr Publié le : 2026-03-03 Temps de lecture : 11 min

Not Running — l’état initial du cycle de vie d’une application mobile lorsqu’elle n’a pas encore été lancée ou a déjà été terminée. Découvrez comment iOS et Android gèrent cet état, quels événements conduisent à la transition depuis Not Running et comment gérer correctement le lancement et la terminaison de l’application dans Swift et Kotlin.

Points clés

  • Not Running — l’application n’est pas chargée en mémoire et n’exécute pas de code; c’est le point d’entrée et de sortie du cycle de vie
  • Lancement — la transition depuis Not Running se produit en tapant sur l’icône de l’application, via un lien profond ou une notification push
  • Terminaison — l’utilisateur ferme l’application d’un balayage, le système la décharge par manque de mémoire ou un crash se produit
  • Démarrage à froid — l’application démarre de zéro, tous les objets sont créés à nouveau, l’état n’est pas restauré depuis le cache
  • Démarrage à chaud — l’application était en Suspended et revient en Active sans initialisation complète

Not Running — qu’est-ce que cet état

Not Running est l’état de base du cycle de vie d’une application mobile dans lequel elle n’est pas chargée dans la RAM de l’appareil et ne consomme pas de ressources système. Dans iOS et Android, cet état signifie l’absence totale de processus et de threads associés à l’application. L’utilisateur voit l’icône de l’application sur l’écran d’accueil, mais l’application elle-même n’est pas active et ne figure pas dans la liste des applications récentes.

Lorsque l’utilisateur tape sur l’icône de l’application, le système crée un nouveau processus, charge le code exécutable en mémoire et initialise toutes les structures de données nécessaires. Ce processus est appelé démarrage à froid (cold start) et est le plus gourmand en ressources en termes de temps de chargement.

Le système peut déplacer l’application vers Not Running depuis n’importe quel autre état. Si l’application est en arrière-plan ou suspendue, le système d’exploitation a le droit de la décharger lorsqu’il n’y a pas assez de RAM pour des tâches de priorité plus élevée — par exemple, pour une application active au premier plan.

Le développeur doit considérer que l’application peut être terminée par le système à tout moment lorsqu’elle est en arrière-plan. Cela signifie que toutes les données non sauvegardées peuvent être perdues. Par conséquent, il est d’une importance cruciale de sauvegarder l’état dans des magasins clé-valeur (UserDefaults, SharedPreferences) ou une base de données locale lors des transitions de Active vers Background.

Comment le système détermine quelle application décharger

iOS utilise des priorités basées sur l’état actuel de l’application: Active a la priorité la plus élevée, suivi de Inactive, Background, Suspended et enfin Not Running — la priorité la plus basse. Android utilise une hiérarchie de processus similaire: le processus de premier plan a la priorité OOM_ADJ = 0, processus Visible = 100, processus Service = 200, processus Background = 300, processus Empty = 400. Plus la valeur est élevée, plus le processus a de chances d’être terminé lorsque la mémoire est faible.

PlateformeÉtatPriorité de déchargeDescription
iOSNot RunningLa plus élevéeApplication non chargée — ne consomme pas de ressources système
iOSSuspendedÉlevéeApplication en mémoire mais sans exécution de code — première cible de décharge
iOSBackgroundMoyenneApplication exécutant une tâche en arrière-plan — déchargée après délai
iOSActiveBasseApplication active — déchargée seulement sous pression mémoire critique
AndroidEmpty ProcessLa plus élevéeProcessus sans composants actifs — supprimé en premier
AndroidBackground ProcessÉlevéeProcessus d’arrière-plan sans Activity visible
AndroidForeground ServiceBasseService avec notification — rarement terminé
AndroidForeground ProcessMinimaleActivity active — terminé en dernier

Démarrage à froid et à chaud d’une application

Démarrage à froid (cold start) se produit lorsque l’application passe directement de Not Running à Active. Le système crée un nouveau processus, charge les classes, initialise les champs statiques, crée le thread principal et démarre le framework d’interface utilisateur. Sur iOS, cela signifie appeler application(_:didFinishLaunchingWithOptions:), sur Android — appeler Application.onCreate() et Activity.onCreate(). Le temps de démarrage à froid peut varier de 200 ms à plusieurs secondes selon la complexité de l’application.

Démarrage à chaud (warm start ou hot start) — l’application était dans l’état Suspended et reprend sans rechargement complet. Le système restaure la dernière pile d’interface utilisateur depuis la mémoire, et l’utilisateur continue de travailler au même endroit. Un démarrage à chaud est considérablement plus rapide qu’un démarrage à froid car la majeure partie du code est déjà chargée en mémoire. Sur iOS, un démarrage à chaud n’appelle pas application(_:didFinishLaunchingWithOptions:), seulement applicationWillEnterForeground et applicationDidBecomeActive.

La différence entre le démarrage à froid et à chaud est cruciale pour l’expérience utilisateur. Lors d’un démarrage à froid, le développeur doit s’assurer que le lancement se produit aussi rapidement que possible — initialisation paresseuse des modules, chargement différé des ressources lourdes, minimisation du travail dans le thread principal au démarrage. Google recommande un démarrage à froid de moins de 500 ms, Apple — moins de 400 ms pour iOS.

kotlin
// Mesure du temps de démarrage à froid dans Android
class App : Application() {
    private var startTime: Long = 0L

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

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

// Démarrer Activity avec initialisation paresseuse
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)
        // Seulement le minimum nécessaire pour la première image
        setupNavigation()
    }

    override fun onPostCreate(savedInstanceState: Bundle?) {
        super.onPostCreate(savedInstanceState)
        // Initialisation lourde après le rendu
        initializeHeavyModules()
    }
}

L’exemple montre la mesure du temps de démarrage à froid dans Android. Application.onCreate() est appelé lors du passage de Not Running à Active. L’horodatage est enregistré au démarrage du processus. L’Activity utilise l’initialisation paresseuse via un délégué lazy pour éviter de bloquer la première image. onPostCreate est l’endroit optimal pour initialiser les modules lourds car l’interface utilisateur a déjà été rendue.

Not Running dans iOS: Swift et AppDelegate

Dans iOS, Not Running est géré via le protocole UIApplicationDelegate. Méthodes clés: application(_:didFinishLaunchingWithOptions:) est appelé après un démarrage à froid, applicationWillTerminate(_:) est appelé avant que l’utilisateur ne termine l’application. Cependant, le système peut terminer l’application sans appeler applicationWillTerminate — par exemple, lors d’une terminaison d’urgence ou d’une pression mémoire. iOS ne garantit pas que cette méthode sera appelée, donc les données doivent être sauvegardées dans applicationDidEnterBackground.

Scénarios de transition vers Not Running sur iOS

L’utilisateur peut terminer manuellement l’application d’un balayage dans l’App Switcher. Le système peut décharger l’application de la mémoire lorsqu’elle est en arrière-plan. L’application peut planter. Dans tous les cas, tous les objets créés lors du lancement sont détruits. L’état qui n’a pas été sauvegardé est perdu à jamais. Dans iOS 13+, il est recommandé d’utiliser NSUserActivity ou le mécanisme de restauration d’état via UIApplication.stateRestorationIdentifier pour préserver l’état.

swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    // Démarrage à froid: l’application est passée de Not Running
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        // Initialisation de l’ensemble minimal de services
        setupAnalytics()
        configureAppearance()
        return true
    }

    // L’application se termine — seulement fermeture manuelle
    func applicationWillTerminate(
        _ application: UIApplication
    ) {
        saveCriticalData()
    }

    // Sauvegarder les données avant de passer en arrière-plan
    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
        )
    }
}

Le code montre la gestion correcte de Not Running sur iOS. applicationWillTerminate n’est appelé que lorsque l’utilisateur termine manuellement l’application. La sauvegarde des données critiques est dupliquée dans applicationDidEnterBackground car cette méthode est garantie d’être appelée avant de passer en arrière-plan. La restauration d’état permet de sauvegarder la pile d’interface utilisateur pour une récupération ultérieure lors d’un démarrage à froid.

Not Running dans Android: Kotlin et processus

Dans Android, Not Running signifie que le processus de l’application n’existe pas. Le système Linux sous-jacent à Android gère les processus via le mécanisme Zygote. Lorsqu’une application est lancée, Zygote bifurque un nouveau processus, charge Dalvik/ART et appelle Application.onCreate(). Android n’a pas d’équivalent direct à applicationWillTerminate — le système peut terminer le processus à tout moment sans avertissement.

Cycle de vie du processus Android

Lorsqu’une Activity est appelée pour la première fois, le système crée le processus, l’Application et l’Activity via la chaîne onCreate → onStart → onResume. Si l’utilisateur appuie sur Retour, l’Activity est détruite (onDestroy), et le processus peut être terminé par le système. Une différence clé avec iOS: dans Android, le processus peut continuer à exister même sans Activities actives — par exemple, si un Foreground Service est en cours d’exécution ou s’il y a un BroadcastReceiver actif.

kotlin
// Gestion de Not Running via SavedStateHandle dans 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 — le premier callback après Not Running
class MyApplication : Application() {

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

SavedStateHandle est un composant d’Android Architecture Components qui sauvegarde automatiquement l’état lors d’une transition vers Not Running et le restaure lors d’un démarrage à froid. Un ViewModel créé via ViewModelProvider survit à la rotation de l’écran et à la destruction de l’Activity. Lorsque le processus se termine, les données de SavedStateHandle sont sérialisées dans un Bundle et sauvegardées dans l’état d’instance sauvegardé.

Raisons de la transition vers Not Running

Not Running se produit pour plusieurs raisons. L’utilisateur ferme manuellement l’application. Le système décharge l’application par manque de mémoire. L’application plante avec une exception. Sur Android, le système peut terminer le processus lors d’une mise à jour massive des applications ou d’un redémarrage de l’appareil. iOS peut terminer l’application lorsqu’une tâche en arrière-plan expire (généralement 30 secondes).

RaisoniOSAndroidPeut être évité
Fermeture manuelle par l’utilisateurBalayage dans App SwitcherBalayage depuis RecentsNon — action de l’utilisateur
Manque de mémoireDéclenchement d’avertissement mémoireonTrimMemory / LMKPartiellement — optimisation mémoire
Plantage de l’applicationNSException / signalUncaughtException / ANROui — gestion des erreurs et signalement des plantages
Expiration de tâche en arrière-plan30 sec pour tâche en arrière-plan10 min pour JobSchedulerOui — planification correcte des tâches
Redémarrage du systèmeapplicationWillTerminate appeléBroadcast ACTION_SHUTDOWNNon — événement système
Mise à jour de l’applicationNe se produit pas (iOS Sandbox)Processus terminé lors de la mise à jour APKNon — mise à jour système

Comment diagnostiquer une transition vers Not Running

Pour iOS, utilisez la journalisation console dans applicationWillTerminate et applicationDidFinishLaunching. Ajoutez un indicateur dans UserDefaults à chaque lancement — si l’indicateur est manquant au prochain démarrage, l’application a été terminée incorrectement. Sur Android, utilisez ActivityManager.isBackgroundRestricted() pour vérifier si l’application peut exécuter des tâches en arrière-plan. Surveillez également onTrimMemory(TRIM_MEMORY_COMPLETE) — c’est un signal que le processus va être terminé.

Bonnes pratiques pour travailler avec Not Running

Première règle — ne supposez jamais que applicationWillTerminate ou onDestroy seront appelés. Sauvegardez les données d’importance critique à chaque transition de Active vers Background. Utilisez des magasins clé-valeur pour les paramètres simples et SQLite/Room pour les données structurées.

Deuxième règle — mesurez le temps de démarrage à froid et optimisez-le. Initialisation paresseuse, minimisation du travail dans le thread principal, préchargement des ressources, utilisation de l’API SplashScreen — tout cela améliore la perception du temps de lancement. Google recommande un démarrage à froid de moins de 200 ms pour une excellente expérience utilisateur.

Troisième règle — implémentez la restauration d’état. Sur iOS, utilisez UIApplication.stateRestorationIdentifier et NSUserActivity. Sur Android, utilisez SavedStateHandle dans ViewModel combiné avec onSaveInstanceState. Cela permettra à l’utilisateur de continuer à travailler au même endroit après un redémarrage de l’application.

Quatrième règle — gérez les launchOptions et Intent avec lesquels l’application a été lancée après Not Running. Liens profonds, notifications push, liens universels — tous sont transmis via les paramètres de lancement. Le développeur doit extraire correctement ces données et diriger l’utilisateur vers l’écran approprié.

swift
// Gestion du lien profond après un démarrage à froid
func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    // Vérifier si une notification est arrivée
    if let notification = launchOptions?[.remoteNotification] as? [String: Any] {
        handleNotification(notification)
    }
    // Vérifier le lien profond
    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)
}

Le code montre la gestion des paramètres de lancement lors d’un démarrage à froid iOS. launchOptions contient les données avec lesquelles le système a lancé l’application. Les notifications, liens profonds et liens universels sont transmis via ce dictionnaire. Le développeur doit gérer correctement tous les scénarios de lancement possibles pour garantir une expérience utilisateur fluide.

Foire aux questions

Que se passe-t-il avec les données lors de la transition vers Not Running?

Les données qui ont été sauvegardées dans le stockage persistant (UserDefaults, Core Data, SharedPreferences, Room) sont conservées. Les données dans la RAM — variables, cache, état ViewModel sans SavedStateHandle — sont irrémédiablement perdues. Par conséquent, il est d’une importance cruciale de sauvegarder l’état de l’application à chaque transition vers Background.

Comment distinguer un démarrage à froid d’un démarrage à chaud sur iOS?

Lors d’un démarrage à froid, application(_:didFinishLaunchingWithOptions:) est appelé. Lors d’un démarrage à chaud (retour de Suspended), cette méthode n’est pas appelée — seuls applicationWillEnterForeground et applicationDidBecomeActive sont déclenchés. Si vous devez effectuer une action uniquement lors d’un démarrage à froid, définissez un indicateur dans didFinishLaunchingWithOptions.

Une application Android peut-elle être en Not Running avec un Service actif?

Oui. Un Foreground Service avec une notification persistante empêche le système de terminer le processus, même si toutes les Activities sont détruites. Un Background Service (startService sans premier plan) peut être arrêté par le système à tout moment. Un Service en cours d’exécution signifie que le processus existe, et ce n’est plus Not Running.

Comment émuler Not Running sur un simulateur?

Sur le simulateur iOS, terminez l’application via l’App Switcher (Cmd+Shift+H deux fois, balayez vers le haut). Sur l’émulateur Android, utilisez adb shell am force-stop com.example.app ou le bouton Stop dans Logcat. Ensuite, relancez l’application — ce sera un démarrage à froid propre depuis Not Running.

Qu’est-ce qu’un kill-switch dans le contexte de Not Running?

Kill-switch est une commande serveur pour la terminaison d’urgence de l’application. Il est utilisé dans les applications bancaires et d’entreprise pour le blocage d’accès à distance. Si l’application reçoit une commande kill, lors du prochain démarrage à froid, elle bloque l’interface utilisateur et demande une réauthentification. Sur iOS, un kill-switch est implémenté via des notifications à distance avec un indicateur de blocage.

Résumé

  • Not Running — l’état initial et final du cycle de vie, l’application n’est pas chargée en mémoire et n’exécute pas de code
  • Démarrage à froid — redémarrage complet de l’application depuis Not Running, nécessite l’initialisation de tous les composants à partir de zéro
  • Démarrage à chaud — retour de Suspended, n’appelle pas didFinishLaunchingWithOptions ni Application.onCreate
  • Sauvegarde des données — il est crucial de l’effectuer lors de la transition vers Background, car Not Running peut survenir à tout moment
  • iOS — applicationWillTerminate n’est pas garanti, l’état est sauvegardé via UserDefaults ou la restauration d’état
  • Android — le processus peut être terminé à tout moment, SavedStateHandle dans ViewModel sauvegarde l’état automatiquement
  • Optimisation du démarrage — initialisation paresseuse, travail minimal dans le thread principal, API SplashScreen pour une première image rapide

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi