תהליכים ומחזור חיים של אפליקציה
קל לארגן דפים בעזרת אוספים
אפשר לשמור ולסווג תוכן על סמך ההעדפות שלך.
ברוב המקרים, כל אפליקציית Android פועלת בתהליך Linux משלה.
התהליך הזה נוצר לאפליקציה כשחלק מהקוד שלה צריך לפעול, והוא נשאר פועל עד שהמערכת צריכה להשתמש בזיכרון שלו לאפליקציות אחרות והוא לא נדרש יותר.
תכונה יוצאת דופן וחיונית ב-Android היא שלא האפליקציה עצמה קובעת את משך החיים של תהליך האפליקציה.
במקום זאת, המערכת קובעת את הדבר על סמך שילוב של החלקים באפליקציה שהמערכת יודעת שהם פועלים, מידת החשיבות של הדברים האלה למשתמש וכמות הזיכרון הכוללת שזמינה במערכת.
חשוב שמפתחי האפליקציות יבינו איך רכיבים שונים של האפליקציה (במיוחד Activity
, Service
ו-BroadcastReceiver
) משפיעים על משך החיים של התהליך של האפליקציה. שימוש שגוי ברכיבים האלה עלול לגרום למערכת להרוג את תהליך האפליקציה בזמן שהוא מבצע עבודה חשובה.
דוגמה נפוצה לבאג במחזור החיים של תהליך היא BroadcastReceiver
שמתחילה שרשור כשהיא מקבלת Intent
ב-method BroadcastReceiver.onReceive()
שלה, ולאחר מכן חוזרת מהפונקציה. אחרי שהוא חוזר, המערכת מתייחסת ל-BroadcastReceiver
כאל אירוע לא פעיל, ותהליך האירוח שלו לא נדרש יותר, אלא אם רכיבים אחרים של האפליקציה פעילים בו.
לכן, המערכת יכולה להרוג את התהליך בכל שלב כדי לפנות זיכרון, וכך היא מפסיקה את החוט שנוצר שפועל בתהליך. הפתרון לבעיה הזו הוא בדרך כלל לתזמן JobService
מה-BroadcastReceiver
כדי שהמערכת תדע שיש פעילות פעילה בתהליך.
כדי לקבוע אילו תהליכים לסגור כשהזיכרון מתחיל להיגמר, מערכת Android ממיינת כל תהליך לפי היררכיית חשיבות על סמך הרכיבים שפועלים בו והמצב של הרכיבים האלה. סוגי התהליכים האלה מופיעים לפי סדר החשיבות הבא:
- תהליך בחזית הוא תהליך שנחוץ למה שהמשתמש עושה כרגע. רכיבים שונים של אפליקציה יכולים לגרום לתהליך שמכיל אותה להיחשב כחזית בדרכים שונות. תהליך נחשב כמי שנמצא בחזית אם מתקיים אחד מהתנאים הבאים:
תמיד יש רק כמה תהליכים כאלה במערכת, והם נהרגים רק כמוצא אחרון אם הזיכרון נמוך כל כך שאפילו התהליכים האלה לא יכולים להמשיך לפעול. בדרך כלל, אם זה קורה, המכשיר הגיע למצב של דפדוף בזיכרון, ולכן הפעולה הזו נדרשת כדי לשמור על תגובה מהירה של ממשק המשתמש.
- תהליך גלוי מבצע עבודה שהמשתמש מודע אליה כרגע, ולכן סגירה שלו משפיעה לרעה באופן ניכר על חוויית המשתמש. תהליך נחשב גלוי בתנאים הבאים:
- הוא מפעיל
Activity
שגלוי למשתמש במסך אבל לא בחזית (השיטה
onPause()
שלו הייתה בשימוש). המצב הזה יכול לקרות, למשל, אם Activity
בחזית מוצג כתיבת דו-שיח שמאפשרת לראות את Activity
הקודם מאחוריה.
- יש לה
Service
שפועל כשירות בחזית, דרך Service.startForeground()
(שמבקש מהמערכת להתייחס לשירות כמשהו שהמשתמש מודע אליו, או למעשה כאילו הוא גלוי).
- הוא מארח שירות שהמערכת משתמשת בו לתכונה מסוימת שהמשתמש מודע לה, כמו טפט חי או שירות של שיטת קלט.
מספר התהליכים האלה שפועלים במערכת מוגבל פחות מתהליכים בחזית, אבל עדיין נשלט באופן יחסי. התהליכים האלה נחשבים חשובים מאוד, והם לא יופסקו אלא אם צריך לעשות זאת כדי לשמור על פעילותם של כל התהליכים בחזית.
- תהליך שירות הוא תהליך שמכיל
Service
שהופעל באמצעות השיטה startService()
. התהליכים האלה לא גלויים למשתמש באופן ישיר, אבל בדרך כלל הם מבצעים פעולות שחשובות למשתמש (כמו העלאה או הורדה של נתוני רשת ברקע). לכן, המערכת תמיד ממשיכה להריץ תהליכים כאלה, אלא אם אין מספיק זיכרון כדי לשמור את כל התהליכים בחזית ובתהליכים הגלויים.
יכול להיות ששירותים שפועלים במשך זמן רב (למשל, 30 דקות או יותר) יורדים ברמת החשיבות כדי שהתהליך שלהם יועבר לרשימה ששמורה במטמון.
אפשר ליצור תהליכים שצריך להריץ לאורך תקופה ארוכה באמצעות setForeground
.
אם מדובר בתהליך תקופתי שדורש זמן ביצוע קפדני, אפשר לתזמן אותו באמצעות AlarmManager
.
מידע נוסף זמין במאמר תמיכה בעובדים לטווח ארוך.
כך אפשר למנוע מצבים שבהם שירותים ארוכי טווח שמנצלים משאבים מיותרים, למשל על ידי דליפת זיכרון, מונעים מהמערכת לספק חוויית משתמש טובה.
- תהליך ששמור במטמון הוא תהליך שלא נדרש כרגע, ולכן המערכת יכולה להרוג אותו לפי הצורך כשיש צורך במשאבים כמו זיכרון במקום אחר. במערכת שפועלת באופן תקין, אלה התהליכים היחידים שמעורבים בניהול המשאבים.
במערכת תקינה תמיד יש כמה תהליכים ששמורים במטמון, כדי לאפשר מעבר יעיל בין האפליקציות, והיא סוגרת באופן קבוע את האפליקציות ששמורות במטמון לפי הצורך.
רק במצבים קריטיים מאוד המערכת מגיעה למצב שבו כל התהליכים ששמורים במטמון נהרגים, והיא צריכה להתחיל להרוג תהליכי שירות.
מאחר שהמערכת יכולה להרוג תהליכים שנשמרו במטמון בכל שלב, האפליקציות צריכות להפסיק את כל העבודה במצב שמאוחסן במטמון. אם האפליקציה צריכה לבצע עבודה קריטית למשתמש, היא צריכה להשתמש באחד מממשקי ה-API שלמעלה כדי להריץ את העבודה ממצב תהליך פעיל.
לעיתים קרובות תהליכים שנשמרו במטמון מכילים מופע אחד או יותר של Activity
שלא גלויים כרגע למשתמש (השיטה onStop()
שלהם הוזמנה והחזירה תשובה).
אם תטמיעו את מחזור החיים של Activity
בצורה נכונה כשהמערכת תהרוג תהליכים כאלה, זה לא ישפיע על חוויית המשתמש כשיחזור לאפליקציה הזו. היא תוכל לשחזר את המצב שנשמר קודם כשהפעילות המשויכת תיווצר מחדש בתהליך חדש. חשוב לזכור שלא בטוח ש-onDestroy()
ייכלל בקריאה במקרה שהמערכת תפסיק תהליך.
פרטים נוספים זמינים במאמר Activity
.
החל מ-Android 13, תהליך של אפליקציה עשוי לקבל זמן ביצוע מוגבל או לא לקבל כלל זמן ביצוע עד שהוא נכנס לאחד מהמצבים הפעילים של מחזור החיים שלמעלה.
התהליכים שנשמרים במטמון נשמרים ברשימה. מדיניות הסדר המדויק של הרשימה הזו היא פרט הטמעה בפלטפורמה. באופן כללי, המערכת מנסה לשמור על תהליכים שימושיים יותר, כמו תהליכים שמארחים את אפליקציית הבית של המשתמש או את הפעילות האחרונה שהמשתמש ראה, לפני תהליכים מסוגים אחרים. אפשר גם להחיל מדיניות אחרת להפסקת תהליכים, כמו הגדרת מגבלות קפדניות על מספר התהליכים המותרים או הגבלת משך הזמן שבו תהליך יכול להישאר במטמון באופן קבוע.
כשהמערכת מחליטה איך לסווג תהליך, היא מבססת את ההחלטה על הרמה החשובה ביותר שנמצאה בין כל הרכיבים הפעילים כרגע בתהליך.
במסמכים של Activity
, Service
ו-BroadcastReceiver
מוסבר בפירוט איך כל אחד מהרכיבים האלה תורם למחזור החיים הכולל של התהליך ושל האפליקציה.
העדיפות של תהליך יכולה גם לעלות על סמך יחסי תלות אחרים שיש לו. לדוגמה, אם תהליך א' משויך ל-Service
עם הדגל Context.BIND_AUTO_CREATE
או משתמש ב-ContentProvider
בתהליך ב', הסיווג של תהליך ב' תמיד חשוב לפחות כמו הסיווג של תהליך א'.
דוגמאות התוכן והקוד שבדף הזה כפופות לרישיונות המפורטים בקטע רישיון לתוכן. Java ו-OpenJDK הם סימנים מסחריים או סימנים מסחריים רשומים של חברת Oracle ו/או של השותפים העצמאיים שלה.
עדכון אחרון: 2025-07-27 (שעון UTC).
[[["התוכן קל להבנה","easyToUnderstand","thumb-up"],["התוכן עזר לי לפתור בעיה","solvedMyProblem","thumb-up"],["סיבה אחרת","otherUp","thumb-up"]],[["חסרים לי מידע או פרטים","missingTheInformationINeed","thumb-down"],["התוכן מורכב מדי או עם יותר מדי שלבים","tooComplicatedTooManySteps","thumb-down"],["התוכן לא עדכני","outOfDate","thumb-down"],["בעיה בתרגום","translationIssue","thumb-down"],["בעיה בדוגמאות/בקוד","samplesCodeIssue","thumb-down"],["סיבה אחרת","otherDown","thumb-down"]],["עדכון אחרון: 2025-07-27 (שעון UTC)."],[],[],null,["# Processes and app lifecycle\n\nIn most cases, every Android application runs in its own Linux process.\nThis process is created for the application when some of its code needs to\nrun and remains running until the system needs to reclaim its memory for use\nby other applications and it is no longer needed.\n\nAn unusual and fundamental feature of Android is that an application process's\nlifetime *isn't* directly controlled by the application itself.\nInstead, it is determined by the system through a combination of the parts of the application\nthat the system knows are running, how important these things are to the user,\nand how much overall memory is available in the system.\n\nIt is important that\napplication developers understand how different application components\n(in particular [Activity](/reference/android/app/Activity), [Service](/reference/android/app/Service),\nand [BroadcastReceiver](/reference/android/content/BroadcastReceiver)) impact the lifetime\nof the application's process. **Not using these components correctly can\nresult in the system killing the application's process while it is doing\nimportant work.**\n\nA common example of a process lifecycle bug is a\n`BroadcastReceiver` that starts a thread when it\nreceives an `Intent` in its [BroadcastReceiver.onReceive()](/reference/android/content/BroadcastReceiver#onReceive(android.content.Context, android.content.Intent))\nmethod and then returns from the function. Once it returns, the system\nconsiders the `BroadcastReceiver` to no longer be active, and its hosting\nprocess to no longer be needed, unless other application components are active in\nit.\n\n\nSo, the system can kill the process at any time to reclaim memory, and in doing so,\nit terminates the spawned thread running in the process. The solution to this problem\nis typically to schedule a [JobService](/reference/android/app/job/JobService)\nfrom the `BroadcastReceiver` so the\nsystem knows that there is active work occurring in the process.\n\nTo determine which processes to kill when low on memory, Android\nplaces each process into an importance hierarchy based on the components running in\nthem and the state of those components. In order of importance, these process types are:\n\n1. A **foreground process** is one that is required for what the user is currently doing. Various application components can cause its containing process to be considered foreground in different ways. A process is considered to be in the foreground if any of the following conditions hold:\n - It is running an [Activity](/reference/android/app/Activity) at the top of the screen that the user is interacting with (its [onResume()](/reference/android/app/Activity#onResume()) method has been called).\n - It has a [BroadcastReceiver](/reference/android/content/BroadcastReceiver) that is currently running (its [BroadcastReceiver.onReceive()](/reference/android/content/BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)) method is executing).\n - It has a [Service](/reference/android/app/Service) that is currently executing code in one of its callbacks ([Service.onCreate()](/reference/android/app/Service#onCreate()), [Service.onStart()](/reference/android/app/Service#onStart(android.content.Intent, int)), or [Service.onDestroy()](/reference/android/app/Service#onDestroy())).\n2. There are only ever a few such processes in the system, and these are only killed as a last resort if memory is so low that not even these processes can continue to run. Generally, if this happens the device has reached a memory paging state, so this action is required to keep the user interface responsive.\n3. A **visible process** is doing work that the user is currently aware of, so killing it has a noticeable negative impact on the user experience. A process is considered visible in the following conditions:\n - It is running an [Activity](/reference/android/app/Activity) that is visible to the user on-screen but not in the foreground (its [onPause()](/reference/android/app/Activity#onPause()) method has been called). This might occur, for example, if the foreground `Activity` is displayed as a dialog that lets the previous `Activity` be seen behind it.\n - It has a [Service](/reference/android/app/Service) that is running as a foreground service, through [Service.startForeground()](/reference/android/app/Service#startForeground(int, android.app.Notification)) (which asks the system to treat the service as something the user is aware of, or essentially as if it were visible).\n - It is hosting a service that the system is using for a particular feature that the user is aware of, such as a live wallpaper or an input method service.\n\n The number of these processes running in the system is less bounded than foreground\n processes, but still relatively controlled. These processes are\n considered extremely important and aren't killed unless doing so is\n required to keep all foreground processes running.\n4. A **service process** is one holding a [Service](/reference/android/app/Service) that has been started with the [startService()](/reference/android/content/Context#startService(android.content.Intent)) method. Though these processes are not directly visible to the user, they are generally doing things that the user cares about (such as background network data upload or download), so the system always keeps such processes running unless there is not enough memory to retain all foreground and visible processes.\n\n Services that have been running for a long time (such as 30 minutes or more) might be\n demoted in importance to let their process drop to the cached list.\n\n Processes that do need to be run over a long period can be created with\n [setForeground](/reference/kotlin/androidx/work/CoroutineWorker#setForeground(androidx.work.ForegroundInfo)).\n If it is a periodic process that requires strict time of execution, it can be\n scheduled through the [AlarmManager](/reference/android/app/AlarmManager).\n For more information, refer to [Support for long-running workers](/topic/libraries/architecture/workmanager/advanced/long-running).\n This helps avoid situations where long-running services that use excessive resources, for\n example, by leaking memory, prevent the system from delivering a good user experience.\n5. A **cached process** is one that is not currently needed, so the system is free to kill it as needed when resources like memory are needed elsewhere. In a normally behaving system, these are the only processes involved in resource management.\n\n \u003cbr /\u003e\n\n A well-running system has multiple cached processes always available, for efficient\n switching between applications, and regularly kills the cached apps as needed.\n Only in very critical situations does the system get to a point where\n all cached processes are killed and it must start killing service processes.\n\n Since cached processes can be killed by the system at any time, apps should cease all work while\n in the cached state. If user-critical work must be performed by the app,\n it should use one of the above APIs to run work from an active process state.\n\n Cached processes often hold one or more [Activity](/reference/android/app/Activity) instances\n that are not currently visible to the user (their\n [onStop()](/reference/android/app/Activity#onStop()) method has been called and has returned).\n Provided they implement their `Activity` lifecycle correctly when the system\n kills such processes, it doesn't impact the user's experience when returning to that app.\n It can restore the previously saved state when the associated activity recreates in\n a new process. Be aware that [onDestroy()](/guide/components/activities/activity-lifecycle#ondestroy)\n is not guaranteed to be called in the case that a process is killed by the system.\n For more details, see [Activity](/reference/android/app/Activity).\n\n Starting in Android 13, an app process may receive limited or no execution time until it enters\n one of the above active lifecycle states.\n\n Cached processes are kept in a list. The exact ordering policy for this list\n is an implementation detail of the platform. Generally, it tries to keep more\n useful processes, such as those hosting the user's home application or the last activity the user saw,\n before other types of processes. Other policies for killing processes can also\n be applied, like setting hard limits on the number of processes allowed or limiting the amount of\n time a process can stay continually cached.\n\nWhen deciding how to classify a process, the system bases its decision on the most\nimportant level found among all the components currently active in the process.\nSee the [Activity](/reference/android/app/Activity), [Service](/reference/android/app/Service), and\n[BroadcastReceiver](/reference/android/content/BroadcastReceiver) documentation for more detail on how\neach of these components contributes to the overall lifecycle of a process and of\nthe application.\n\nA process's priority might also be increased based on other dependencies\na process has to it. For example, if process A has bound to a\n[Service](/reference/android/app/Service) with\nthe [Context.BIND_AUTO_CREATE](/reference/android/content/Context#BIND_AUTO_CREATE)\nflag or is using a\n[ContentProvider](/reference/android/content/ContentProvider) in process B, then process B's\nclassification is always at least as important as process A's."]]