Not Running — mobil tətbiqin hələ işə salınmadığı və ya artıq işini başa çatdırdığı həyat dövrünün ilkin vəziyyətidir. iOS və Android sisteminin bu vəziyyəti necə idarə etdiyini, hansı hadisələrin Not Running-dən keçidə səbəb olduğunu və Swift və Kotlin-də tətbiqin işə salınması və başa çatdırılmasının necə düzgün işlənəcəyini öyrənin.
Əsas məqamlar
Not Running — mobil tətbiqin həyat dövrünün əsas vəziyyətidir, burada tətbiq cihazın operativ yaddaşına yüklənməyib və sistem resurslarını sərf etmir. iOS və Android-də bu vəziyyət tətbiqlə əlaqəli proses və axınların tam olmaması deməkdir. İstifadəçi tətbiqin ikonasını iş masasında görür, lakin tətbiqin özü aktiv deyil və son istifadə olunanlar siyahısında deyil.
İstifadəçi ikonaya toxunduqda sistem yeni proses yaradır, icra olunan kodu yaddaşa yükləyir və bütün lazımi məlumat strukturlarını inisializasiya edir. Bu proses soyuq başlanğıc (cold start) adlanır və yükləmə müddəti baxımından ən resurs tələb edəndir.
Sistem tətbiqi hər hansı digər vəziyyətdən Not Running-ə keçirə bilər. Tətbiq fondadırsa (Background) və ya dayandırılıbsa (Suspended), əməliyyat sistemi daha prioritet tapşırıqlar üçün operativ yaddaş çatışmazlığında onu boşaltmaq hüququna malikdir — məsələn, ön planda olan aktiv tətbiq üçün.
Proqramçı nəzərə almalıdır ki, tətbiq sistem tərəfindən istənilən anda başa çatdırıla bilər, o fonda olduqda. Bu o deməkdir ki, bütün saxlanılmamış məlumatlar itirilə bilər. Buna görə də Active-dən Background-a keçidlərdə vəziyyəti açar-dəyər anbarlarında (UserDefaults, SharedPreferences) və ya yerli verilənlər bazasında saxlamaq kritik əhəmiyyətlidir.
iOS tətbiqin cari vəziyyətinə əsaslanan prioritetlərdən istifadə edir: Active ən yüksək prioritetə malikdir, sonra Inactive, Background, Suspended və nəhayət Not Running — minimal prioritet. Android oxşar proses iyerarxiyasından istifadə edir: Foreground prosesi OOM_ADJ = 0 prioritetinə malikdir, Visible proses = 100, Service proses = 200, Background proses = 300, Empty proses = 400. Dəyər nə qədər yüksəkdirsə, yaddaş çatışmazlığında prosesin başa çatdırılma ehtimalı bir o qədər yüksəkdir.
| Platforma | Vəziyyət | Boşaltma prioriteti | Təsvir |
|---|---|---|---|
| iOS | Not Running | Ən yüksək | Tətbiq yüklənməyib — sistem resursu sərf edilmir |
| iOS | Suspended | Yüksək | Tətbiq yaddaşdadır, lakin kod icra edilmir — boşaltma üçün ilk hədəf |
| iOS | Background | Orta | Tətbiq fon tapşırığını yerinə yetirir — vaxt aşımından sonra boşaldılır |
| iOS | Active | Aşağı | Aktiv tətbiq — yalnız kritik yaddaş çatışmazlığında boşaldılır |
| Android | Empty Process | Ən yüksək | Aktiv komponentləri olmayan proses — ilk silinən |
| Android | Background Process | Yüksək | Görünən Activity olmayan fon prosesi |
| Android | Foreground Service | Aşağı | Bildirişli xidmət — nadir hallarda başa çatdırılır |
| Android | Foreground Process | Minimal | Aktiv Activity — ən son başa çatdırılır |
Soyuq başlanğıc (cold start) tətbiq Not Running-dən birbaşa Active-ə keçdikdə baş verir. Sistem yeni proses yaradır, sinifləri yükləyir, statik sahələri inisializasiya edir, əsas axını yaradır və UI çərçivəsini işə salır. iOS-da bu application(_:didFinishLaunchingWithOptions:) çağırışı, Android-də isə Application.onCreate() və Activity.onCreate() çağırışı deməkdir. Soyuq başlanğıcın müddəti tətbiqin mürəkkəbliyindən asılı olaraq 200 ms-dən bir neçə saniyəyə qədər ola bilər.
İsti başlanğıc (warm start və ya hot start) — tətbiq Suspended vəziyyətində idi və tam yenidən yükləmə olmadan işə qayıdır. Sistem sonuncu UI yığınını yaddaşdan bərpa edir və istifadəçi işə eyni yerdən davam edir. İsti başlanğıc soyuqdan əhəmiyyətli dərəcədə sürətlidir, çünki kodun çox hissəsi artıq yaddaşa yüklənib. iOS-da isti başlanğıc application(_:didFinishLaunchingWithOptions:) çağırmır, yalnız applicationWillEnterForeground və applicationDidBecomeActive çağırır.
Soyuq və isti başlanğıc arasındakı fərq istifadəçi təcrübəsi üçün kritikdir. Soyuq başlanğıcda proqramçı işə salmanın mümkün qədər sürətli olmasını təmin etməlidir — modulların tənbəl inisializasiyası, ağır resursların təxirə salınmış yüklənməsi, başlanğıcda əsas axında işin minimallaşdırılması. Google tövsiyə edir soyuq başlanğıc 500 ms-dən çox olmamalıdır, Apple — iOS üçün 400 ms-dən çox olmamalıdır.
// Androiddə soyuq başlanğıc vaxtının ölçülməsi
class App : Application() {
private var startTime: Long = 0L
override fun onCreate() {
super.onCreate()
startTime = System.currentTimeMillis()
}
fun getStartupTime(): Long {
return System.currentTimeMillis() - startTime
}
}
// Activity-nin tənbəl inisializasiya ilə işə salınması
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)
// Yalnız ilk kadr üçün lazımi minimum
setupNavigation()
}
override fun onPostCreate(savedInstanceState: Bundle?) {
super.onPostCreate(savedInstanceState)
// Renderdən sonra ağır inisializasiya
initializeHeavyModules()
}
}Nümunədə Android-də soyuq başlanğıc vaxtının ölçülməsi göstərilir. Application.onCreate() Not Running-dən Active-ə keçid zamanı çağırılır. Vaxt damğası prosesin başlanğıcında qeydə alınır. Activity ilk kadrı bloklamamaq üçün lazy-delegat vasitəsilə tənbəl inisializasiyadan istifadə edir. onPostCreate ağır modulların inisializasiyası üçün optimal yerdir, çünki UI artıq çəkilib.
iOS-da Not Running UIApplicationDelegate delegatı vasitəsilə idarə olunur. Əsas metodlar: application(_:didFinishLaunchingWithOptions:) soyuq başlanğıcdan sonra çağırılır, applicationWillTerminate(_:) tətbiqin istifadəçi tərəfindən başa çatdırılmasından əvvəl çağırılır. Sistem applicationWillTerminate çağırmadan tətbiqi başa çatdıra bilər — məsələn, qəza başa çatması və ya yaddaşın boşaldılması zamanı. iOS bu metodun çağırılmasına zəmanət vermir, buna görə də məlumatları applicationDidEnterBackground-da saxlamaq lazımdır.
İstifadəçi əl ilə tətbiqi App Switcher-də sürüşdürmə ilə başa çatdıra bilər. Sistem tətbiqi fonda yaddaşdan boşalda bilər. Tətbiq qəza ilə başa çata bilər (crash). Bütün hallarda işə salma zamanı yaradılmış bütün obyektlər məhv edilir. Saxlanılmamış vəziyyət geri qaytarılmaz şəkildə itirilir. iOS 13+ vəziyyəti saxlamaq üçün NSUserActivity və ya UIApplication.stateRestorationIdentifier vasitəsilə state restoration mexanizmindən istifadə etmək tövsiyə olunur.
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
// Soyuq başlanğıc: tətbiq Not Running-dən keçdi
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Minimal xidmət dəstinin inisializasiyası
setupAnalytics()
configureAppearance()
return true
}
// Tətbiq işi bitirir — yalnız əl ilə bağlama
func applicationWillTerminate(
_ application: UIApplication
) {
saveCriticalData()
}
// Fona keçməzdən əvvəl məlumatların saxlanması
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
)
}
}Kod iOS-da Not Running-in düzgün işlənməsini göstərir. applicationWillTerminate yalnız istifadəçi tərəfindən əl ilə başa çatdırmada çağırılır. Kritik məlumatların saxlanması applicationDidEnterBackground-da təkrarlanır, çünki bu metod fonda keçidən əvvəl çağırılacağına zəmanət verilir. State restoration soyuq başlanğıcda sonradan bərpa etmək üçün UI yığınını saxlamağa imkan verir.
Android-də Not Running tətbiq prosesinin mövcud olmaması deməkdir. Android-in əsasında duran Linux sistemi prosesləri Zygote mexanizmi vasitəsilə idarə edir. Tətbiq işə salındıqda Zygote yeni prosesi fork edir, Dalvik/ART yükləyir və Application.onCreate() çağırır. Android-də applicationWillTerminate-in birbaşa analoqu yoxdur — sistem xəbərdarlıq etmədən prosesi istənilən anda başa çatdıra bilər.
Activity ilk dəfə çağırıldıqda sistem proses, Application və Activity-ni onCreate → onStart → onResume zənciri vasitəsilə yaradır. İstifadəçi Back düyməsini basarsa, Activity məhv edilir (onDestroy) və proses sistem tərəfindən başa çatdırıla bilər. iOS-dan əsas fərq: Android-də proses aktiv Activity olmadan da mövcud ola bilər — məsələn, Foreground Service işləyirsə və ya aktiv BroadcastReceiver varsa.
// ViewModel-də SavedStateHandle vasitəsilə Not Running-in işlənməsi
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-dən sonra ilk geri çağırış
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
initCrashReporter()
initDependencyInjection()
}
}SavedStateHandle — Not Running-ə keçid zamanı avtomatik olaraq vəziyyəti saxlayan və soyuq başlanğıcda onu bərpa edən Android Architecture Components komponentidir. ViewModelProvider vasitəsilə yaradılmış ViewModel ekranın dönməsinə və Activity-nin məhvinə davam gətirir. Proses başa çatdıqda SavedStateHandle-dan məlumatlar Bundle-ə seriyalaşdırılır və saved instance state-də saxlanılır.
Not Running bir neçə səbəbdən baş verir. İstifadəçi əl ilə tətbiqi bağlayır. Sistem yaddaş çatışmazlığında tətbiqi boşaldır. Tətbiq istisna ilə qəza başa çatır. Android-də sistem tətbiqlərin kütləvi yenilənməsi və ya cihazın yenidən başladılması zamanı prosesi başa çatdıra bilər. iOS fon tapşırığının vaxt aşımında (adətən 30 saniyə) tətbiqi başa çatdıra bilər.
| Səbəb | iOS | Android | Qarşısını almaq imkanı |
|---|---|---|---|
| İstifadəçi tərəfindən əl ilə bağlama | App Switcher-də sürüşdürmə | Recents-dən sürüşdürmə | Xeyr — istifadəçi hərəkəti |
| Yaddaş çatışmazlığı | Memory warning-in işə düşməsi | onTrimMemory / LMK | Qismən — yaddaş optimallaşdırması |
| Tətbiqin crash-i | NSException / siqnal | UncaughtException / ANR | Bəli — səhv idarəetməsi və crash-reporting |
| Fon tapşırığının vaxt aşımı | Background task üçün 30 san | JobScheduler üçün 10 dəq | Bəli — düzgün tapşırıq planlaması |
| ƏS-nin yenidən başladılması | applicationWillTerminate çağırışı | Broadcast ACTION_SHUTDOWN | Xeyr — sistem hadisəsi |
| Tətbiqin yenilənməsi | Baş vermir (iOS Sandbox) | Proses APK yenilənməsində başa çatır | Xeyr — sistem yenilənməsi |
iOS üçün applicationWillTerminate və applicationDidFinishLaunching-də konsol loqundan istifadə edin. Hər işə salmada UserDefaults-a bayraq əlavə edin — əgər növbəti başlanğıcda bayraq yoxdursa, tətbiq düzgün başa çatdırılmayıb. Android-də ActivityManager.isBackgroundRestricted() istifadə edin ki, tətbiqin fon tapşırıqlarını işə salıb sala bilməyəcəyini yoxlayın. Həmçinin onTrimMemory(TRIM_MEMORY_COMPLETE) izləyin — bu prosesin başa çatdırılacağına işarədir.
Birinci qayda — heç vaxt applicationWillTerminate və ya onDestroy çağırılacağına güvənməyin. Kritik əhəmiyyətli məlumatları Active-dən Background-a hər keçid zamanı saxlayın. Sadə parametrlər üçün açar-dəyər anbarlarından, strukturlaşdırılmış məlumatlar üçün SQLite/Room-dan istifadə edin.
İkinci qayda — soyuq başlanğıc vaxtını ölçün və optimallaşdırın. Tənbəl inisializasiya, əsas axında işin minimallaşdırılması, resursların əvvəlcədən yüklənməsi, SplashScreen API-dən istifadə — bunların hamısı başlanğıc vaxtının qavranılmasını yaxşılaşdırır. Google tövsiyə edir mükəmməl UX üçün soyuq başlanğıc 200 ms-dən az olmalıdır.
Üçüncü qayda — State Restoration tətbiq edin. iOS-da UIApplication.stateRestorationIdentifier və NSUserActivity istifadə edin. Android-də ViewModel-də SavedStateHandle-i onSaveInstanceState ilə birlikdə istifadə edin. Bu, istifadəçiyə tətbiq yenidən başladıqdan sonra işə eyni yerdən davam etməyə imkan verəcək.
Dördüncü qayda — Not Running-dən sonra tətbiqin işə salındığı launchOptions və Intent-ları emal edin. Deep linklər, push bildirişləri, universal keçidlər — bunların hamısı başlanğıc parametrləri vasitəsilə ötürülür. Proqramçı bu məlumatları düzgün çıxarmalı və istifadəçini müvafiq ekrana yönləndirməlidir.
// Soyuq başlanğıcdan sonra deep link-in işlənməsi
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Bildirişin gəlib-gəlmədiyinin yoxlanılması
if let notification = launchOptions?[.remoteNotification] as? [String: Any] {
handleNotification(notification)
}
// Deep link-in yoxlanılması
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)
}Kod iOS soyuq başlanğıcında başlanğıc parametrlərinin işlənməsini göstərir. launchOptions sistemin tətbiqi işə saldığı məlumatları ehtiva edir. Bildirişlər, deep linklər və universal keçidlər bu lüğət vasitəsilə ötürülür. Proqramçı problemsiz istifadəçi təcrübəsini təmin etmək üçün bütün mümkün başlanğıc ssenarilərini düzgün emal etməlidir.
Tez-tez verilən suallar
Daimi yaddaşda saxlanılan məlumatlar (UserDefaults, Core Data, SharedPreferences, Room) qorunur. Operativ yaddaşdakı məlumatlar — dəyişənlər, keş, SavedStateHandle olmadan ViewModel vəziyyəti — geri qaytarılmaz şəkildə itirilir. Buna görə də hər fon keçidində tətbiq vəziyyətini saxlamaq kritik əhəmiyyətlidir.
Soyuq başlanğıcda application(_:didFinishLaunchingWithOptions:) çağırılır. İsti başlanğıcda (Suspended-dən qayıtma) bu metod çağırılmır — yalnız applicationWillEnterForeground və applicationDidBecomeActive işləyir. Yalnız soyuq başlanğıcda hərəkət etmək lazımdırsa, didFinishLaunchingWithOptions-da bayraq qoyun.
Bəli. Foreground Service daimi bildirişlə bütün Activity-lər məhv edilsə belə prosesin sistem tərəfindən başa çatdırılmasının qarşısını alır. Background Service (foreground olmadan startService) istənilən vaxt sistem tərəfindən dayandırıla bilər. İşləyən Service prosesin mövcud olduğunu göstərir və bu artıq Not Running deyil.
iOS simulyatorunda tətbiqi App Switcher vasitəsilə başa çatdırın (Cmd+Shift+H iki dəfə, yuxarı sürüşdürün). Android emulyatorunda adb shell am force-stop com.example.app istifadə edin və ya Logcat-də Stop düyməsini basın. Bundan sonra tətbiqi yenidən işə salın — bu Not Running-dən təmiz soyuq başlanğıc olacaq.
Kill-switch — tətbiqin təcili başa çatdırılması üçün server əmridir. Bank və korporativ tətbiqlərdə uzaqdan girişi bloklamaq üçün istifadə olunur. Tətbiq kill əmri alıbsa, növbəti soyuq başlanğıcda UI bloklayır və yenidən avtorizasiya tələb edir. iOS-da kill-switch bloklama bayrağı olan remote notifications vasitəsilə tətbiq edilir.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun