Not Running — keadaan awal siklus hidup aplikasi mobile, di mana aplikasi belum dijalankan atau sudah selesai beroperasi. Pelajari bagaimana sistem iOS dan Android mengelola keadaan ini, peristiwa apa yang menyebabkan transisi dari Not Running dan cara menangani dengan benar peluncuran dan penghentian aplikasi di Swift dan Kotlin.
Poin Utama
Not Running — adalah keadaan dasar siklus hidup aplikasi mobile, di mana aplikasi tidak dimuat ke dalam RAM perangkat dan tidak mengonsumsi sumber daya sistem. Di iOS dan Android, keadaan ini berarti tidak adanya proses dan thread yang terkait dengan aplikasi. Pengguna melihat ikon aplikasi di desktop, tetapi aplikasi itu sendiri tidak aktif dan tidak ada dalam daftar terbaru.
Ketika pengguna mengetuk ikon, sistem membuat proses baru, memuat kode yang dapat dieksekusi ke memori dan menginisialisasi semua struktur data yang diperlukan. Proses ini disebut start dingin (cold start) dan merupakan yang paling membutuhkan sumber daya dalam hal waktu pemuatan.
Sistem dapat memindahkan aplikasi ke Not Running dari keadaan lain mana pun. Jika aplikasi berada di latar belakang (Background) atau ditangguhkan (Suspended), sistem operasi berhak membongkarnya saat kekurangan RAM untuk tugas yang lebih prioritas — misalnya, untuk aplikasi aktif di latar depan.
Pengembang harus menyadari bahwa aplikasi dapat dihentikan oleh sistem kapan saja saat berada di latar belakang. Ini berarti semua data yang belum disimpan dapat hilang. Oleh karena itu, sangat penting untuk menyimpan keadaan di penyimpanan kunci-nilai (UserDefaults, SharedPreferences) atau di basis data lokal saat transisi dari Active ke Background.
iOS menggunakan prioritas berdasarkan keadaan aplikasi saat ini: Active memiliki prioritas tertinggi, kemudian Inactive, Background, Suspended dan akhirnya Not Running — prioritas minimal. Android menggunakan hierarki proses yang serupa: proses Foreground memiliki prioritas OOM_ADJ = 0, proses Visible = 100, proses Service = 200, proses Background = 300, proses Empty = 400. Semakin tinggi nilainya, semakin besar kemungkinan proses akan dihentikan saat kekurangan memori.
| Platform | Keadaan | Prioritas pembongkaran | Deskripsi |
|---|---|---|---|
| iOS | Not Running | Tertinggi | Aplikasi tidak dimuat — sumber daya sistem tidak dikonsumsi |
| iOS | Suspended | Tinggi | Aplikasi di memori, tetapi kode tidak dijalankan — target pertama untuk pembongkaran |
| iOS | Background | Sedang | Aplikasi menjalankan tugas latar belakang — dibongkar setelah batas waktu |
| iOS | Active | Rendah | Aplikasi aktif — hanya dibongkar saat kekurangan memori kritis |
| Android | Empty Process | Tertinggi | Proses tanpa komponen aktif — dihapus pertama |
| Android | Background Process | Tinggi | Proses latar belakang tanpa Activity yang terlihat |
| Android | Foreground Service | Rendah | Layanan dengan notifikasi — jarang dihentikan |
| Android | Foreground Process | Minimal | Activity aktif — dihentikan paling akhir |
Start dingin (cold start) terjadi ketika aplikasi beralih dari Not Running langsung ke Active. Sistem membuat proses baru, memuat kelas, menginisialisasi bidang statis, membuat thread utama dan menjalankan kerangka UI. Di iOS ini berarti pemanggilan application(_:didFinishLaunchingWithOptions:), di Android — pemanggilan Application.onCreate() dan Activity.onCreate(). Waktu start dingin dapat berkisar dari 200 ms hingga beberapa detik tergantung pada kompleksitas aplikasi.
Start panas (warm start atau hot start) — aplikasi berada dalam keadaan Suspended dan kembali beroperasi tanpa pemuatan ulang penuh. Sistem memulihkan tumpukan UI terakhir dari memori dan pengguna melanjutkan pekerjaan dari tempat yang sama. Start panas secara signifikan lebih cepat daripada start dingin, karena sebagian besar kode sudah dimuat ke memori. Di iOS, start panas tidak memanggil application(_:didFinishLaunchingWithOptions:), hanya applicationWillEnterForeground dan applicationDidBecomeActive.
Perbedaan antara start dingin dan panas sangat penting untuk pengalaman pengguna. Pada start dingin, pengembang harus memastikan bahwa peluncuran terjadi secepat mungkin — inisialisasi malas modul, pemuatan tertunda sumber daya berat, minimalisasi pekerjaan di thread utama saat peluncuran. Google merekomendasikan start dingin tidak lebih dari 500 ms, Apple — tidak lebih dari 400 ms untuk iOS.
// Mengukur waktu start dingin di Android
class App : Application() {
private var startTime: Long = 0L
override fun onCreate() {
super.onCreate()
startTime = System.currentTimeMillis()
}
fun getStartupTime(): Long {
return System.currentTimeMillis() - startTime
}
}
// Menjalankan Activity dengan inisialisasi malas
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)
// Hanya minimum yang diperlukan untuk bingkai pertama
setupNavigation()
}
override fun onPostCreate(savedInstanceState: Bundle?) {
super.onPostCreate(savedInstanceState)
// Inisialisasi berat setelah rendering
initializeHeavyModules()
}
}Contoh menunjukkan pengukuran waktu start dingin di Android. Application.onCreate() dipanggil saat transisi dari Not Running ke Active. Stempel waktu dicatat saat proses dimulai. Activity menggunakan inisialisasi malas melalui lazy-delegate agar tidak memblokir bingkai pertama. onPostCreate adalah tempat optimal untuk inisialisasi modul berat, karena UI sudah dirender.
Di iOS, Not Running dikelola melalui delegasi UIApplicationDelegate. Metode kunci: application(_:didFinishLaunchingWithOptions:) dipanggil setelah start dingin, applicationWillTerminate(_:) dipanggil sebelum penghentian aplikasi oleh pengguna. Sistem dapat menghentikan aplikasi tanpa memanggil applicationWillTerminate — misalnya, saat penghentian darurat atau pembongkaran memori. iOS tidak menjamin pemanggilan metode ini, oleh karena itu data harus disimpan di applicationDidEnterBackground.
Pengguna dapat menghentikan aplikasi secara manual dengan swipe di App Switcher. Sistem dapat membongkar aplikasi dari memori di latar belakang. Aplikasi dapat berhenti secara darurat (crash). Dalam semua kasus, semua objek yang dibuat saat peluncuran dihancurkan. Keadaan yang tidak disimpan akan hilang secara permanen. Di iOS 13+ untuk menyimpan keadaan disarankan menggunakan NSUserActivity atau mekanisme state restoration melalui UIApplication.stateRestorationIdentifier.
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
// Start dingin: aplikasi beralih dari Not Running
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Inisialisasi set layanan minimal
setupAnalytics()
configureAppearance()
return true
}
// Aplikasi menghentikan operasi — hanya penutupan manual
func applicationWillTerminate(
_ application: UIApplication
) {
saveCriticalData()
}
// Menyimpan data sebelum masuk ke latar belakang
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
)
}
}Kode menunjukkan penanganan Not Running yang benar di iOS. applicationWillTerminate hanya dipanggil saat penghentian manual oleh pengguna. Penyimpanan data kritis diduplikasi di applicationDidEnterBackground, karena metode ini dijamin dipanggil sebelum masuk ke latar belakang. State restoration memungkinkan menyimpan tumpukan UI untuk pemulihan selanjutnya saat start dingin.
Di Android, Not Running berarti proses aplikasi tidak ada. Sistem Linux yang mendasari Android mengelola proses melalui mekanisme Zygote. Saat aplikasi dijalankan, Zygote melakukan fork proses baru, memuat Dalvik/ART dan memanggil Application.onCreate(). Di Android tidak ada analog langsung dari applicationWillTerminate — sistem dapat menghentikan proses kapan saja tanpa peringatan.
Ketika Activity dipanggil untuk pertama kalinya, sistem membuat proses, Application dan Activity melalui rantai onCreate → onStart → onResume. Jika pengguna menekan Back, Activity dihancurkan (onDestroy) dan proses dapat dihentikan oleh sistem. Perbedaan utama dengan iOS: di Android, proses dapat terus ada bahkan tanpa Activity yang aktif — misalnya, jika Foreground Service berjalan atau ada BroadcastReceiver aktif.
// Menangani Not Running melalui SavedStateHandle di 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 — panggilan balik pertama setelah Not Running
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
initCrashReporter()
initDependencyInjection()
}
}SavedStateHandle — komponen Android Architecture Components yang secara otomatis menyimpan keadaan saat transisi ke Not Running dan memulihkannya saat start dingin. ViewModel yang dibuat melalui ViewModelProvider bertahan dari rotasi layar dan penghancuran Activity. Saat proses dihentikan, data dari SavedStateHandle diserialisasi ke Bundle dan disimpan di saved instance state.
Not Running terjadi karena beberapa alasan. Pengguna menutup aplikasi secara manual. Sistem membongkar aplikasi saat kekurangan memori. Aplikasi berhenti secara darurat dengan pengecualian. Di Android, sistem dapat menghentikan proses saat pembaruan massal aplikasi atau restart perangkat. iOS dapat menghentikan aplikasi saat batas waktu tugas latar belakang (biasanya 30 detik).
| Penyebab | iOS | Android | Kemungkinan pencegahan |
|---|---|---|---|
| Penutupan manual oleh pengguna | Swipe di App Switcher | Swipe dari Recents | Tidak — tindakan pengguna |
| Kekurangan memori | Pengaktifan memory warning | onTrimMemory / LMK | Sebagian — optimasi memori |
| Crash aplikasi | NSException / sinyal | UncaughtException / ANR | Ya — penanganan kesalahan dan crash-reporting |
| Batas waktu tugas latar belakang | 30 detik untuk Background task | 10 menit untuk JobScheduler | Ya — perencanaan tugas yang tepat |
| Restart OS | Pemanggilan applicationWillTerminate | Broadcast ACTION_SHUTDOWN | Tidak — peristiwa sistem |
| Pembaruan aplikasi | Tidak terjadi (iOS Sandbox) | Proses berhenti saat pembaruan APK | Tidak — pembaruan sistem |
Untuk iOS, gunakan logging konsol di applicationWillTerminate dan applicationDidFinishLaunching. Tambahkan bendera di UserDefaults setiap kali peluncuran — jika pada start berikutnya bendera tidak ada, aplikasi telah dihentikan secara tidak benar. Di Android gunakan ActivityManager.isBackgroundRestricted() untuk memeriksa apakah aplikasi dapat menjalankan tugas latar belakang. Juga pantau onTrimMemory(TRIM_MEMORY_COMPLETE) — ini adalah sinyal bahwa proses akan dihentikan.
Aturan pertama — jangan pernah menganggap bahwa applicationWillTerminate atau onDestroy akan dipanggil. Simpan data yang sangat penting setiap kali transisi dari Active ke Background. Gunakan penyimpanan kunci-nilai untuk pengaturan sederhana dan SQLite/Room untuk data terstruktur.
Aturan kedua — ukur waktu start dingin dan optimalkan. Inisialisasi malas, minimalisasi pekerjaan di thread utama, pemuatan awal sumber daya, penggunaan SplashScreen API — semua ini meningkatkan persepsi waktu peluncuran. Google merekomendasikan start dingin kurang dari 200 ms untuk UX yang sangat baik.
Aturan ketiga — implementasikan State Restoration. Di iOS gunakan UIApplication.stateRestorationIdentifier dan NSUserActivity. Di Android gunakan SavedStateHandle di ViewModel bersama dengan onSaveInstanceState. Ini akan memungkinkan pengguna melanjutkan pekerjaan dari tempat yang sama setelah restart aplikasi.
Aturan keempat — tangani launchOptions dan Intent yang digunakan untuk menjalankan aplikasi setelah Not Running. Deep link, notifikasi push, tautan universal — semuanya diteruskan melalui parameter peluncuran. Pengembang harus mengekstrak data ini dengan benar dan mengarahkan pengguna ke layar yang sesuai.
// Menangani deep link setelah start dingin
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Memeriksa apakah notifikasi tiba
if let notification = launchOptions?[.remoteNotification] as? [String: Any] {
handleNotification(notification)
}
// Memeriksa 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)
}Kode menunjukkan penanganan parameter peluncuran saat start dingin di iOS. launchOptions berisi data yang digunakan sistem untuk menjalankan aplikasi. Notifikasi, deep link dan tautan universal diteruskan melalui kamus ini. Pengembang harus menangani semua skenario peluncuran yang mungkin untuk memastikan pengalaman pengguna yang mulus.
Pertanyaan yang Sering Diajukan
Data yang disimpan di penyimpanan permanen (UserDefaults, Core Data, SharedPreferences, Room) tetap terjaga. Data di RAM — variabel, cache, keadaan ViewModel tanpa SavedStateHandle — hilang secara permanen. Oleh karena itu, sangat penting untuk menyimpan keadaan aplikasi setiap kali transisi ke latar belakang.
Saat start dingin, application(_:didFinishLaunchingWithOptions:) dipanggil. Saat start panas (kembali dari Suspended), metode ini tidak dipanggil — hanya applicationWillEnterForeground dan applicationDidBecomeActive yang aktif. Jika Anda perlu melakukan tindakan hanya saat start dingin, setel bendera di didFinishLaunchingWithOptions.
Ya. Foreground Service dengan notifikasi permanen mencegah penghentian proses oleh sistem, bahkan jika semua Activity dihancurkan. Background Service (startService tanpa foreground) dapat dihentikan oleh sistem kapan saja. Service yang berjalan berarti proses ada dan ini bukan lagi Not Running.
Di simulator iOS, hentikan aplikasi melalui App Switcher (Cmd+Shift+H dua kali, swipe ke atas). Di emulator Android, gunakan adb shell am force-stop com.example.app atau tombol Stop di Logcat. Kemudian jalankan aplikasi lagi — ini akan menjadi start dingin bersih dari Not Running.
Kill-switch — perintah server untuk penghentian darurat aplikasi. Digunakan di aplikasi perbankan dan perusahaan untuk memblokir akses jarak jauh. Jika aplikasi menerima perintah kill, pada start dingin berikutnya akan memblokir UI dan meminta otorisasi ulang. Di iOS, kill-switch diimplementasikan melalui remote notifications dengan bendera pemblokiran.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga