فرآیندها و چرخه عمر برنامه

در بیشتر موارد، هر برنامه اندرویدی در فرآیند لینوکس خود اجرا می شود. این فرآیند زمانی برای برنامه ایجاد می شود که برخی از کدهای آن باید اجرا شوند و تا زمانی که سیستم نیاز به بازیابی حافظه خود برای استفاده توسط سایر برنامه ها داشته باشد و دیگر نیازی به آن نباشد در حال اجرا باقی می ماند.

یکی از ویژگی‌های غیرعادی و اساسی اندروید این است که طول عمر یک برنامه کاربردی مستقیماً توسط خود برنامه کنترل نمی‌شود . در عوض، سیستم از طریق ترکیبی از بخش‌هایی از برنامه که سیستم می‌داند در حال اجرا هستند، تعیین می‌کند که این موارد چقدر برای کاربر مهم هستند و چه مقدار حافظه کلی در سیستم موجود است.

این مهم است که توسعه دهندگان برنامه بفهمند که چگونه مؤلفه های مختلف برنامه (به ویژه Activity ، Service و BroadcastReceiver ) بر طول عمر فرآیند برنامه تأثیر می گذارد. عدم استفاده صحیح از این مؤلفه‌ها می‌تواند منجر به از بین رفتن فرآیند برنامه در حین انجام کارهای مهم شود.

یک مثال متداول از یک اشکال چرخه حیات فرآیند، BroadcastReceiver است که وقتی یک Intent در متد BroadcastReceiver.onReceive() خود دریافت می کند، یک رشته را شروع می کند و سپس از تابع برمی گردد. پس از بازگشت، سیستم BroadcastReceiver را دیگر فعال نمی داند و فرآیند میزبانی آن دیگر مورد نیاز نیست، مگر اینکه سایر اجزای برنامه در آن فعال باشند.

بنابراین، سیستم می‌تواند در هر زمانی فرآیند را برای بازیابی حافظه از بین ببرد و با انجام این کار، نخ ایجاد شده در فرآیند را خاتمه می‌دهد. راه حل این مشکل معمولاً برنامه ریزی JobService از BroadcastReceiver است تا سیستم بداند که کار فعالی در این فرآیند در حال انجام است.

برای تعیین اینکه کدام فرآیندها در صورت کمبود حافظه حذف شوند، Android هر فرآیند را در یک سلسله مراتب اهمیت بر اساس مؤلفه های در حال اجرا در آنها و وضعیت آن مؤلفه ها قرار می دهد. به ترتیب اهمیت، این انواع فرآیند عبارتند از:

  1. فرآیند پیش زمینه فرآیندی است که برای کاری که کاربر در حال حاضر انجام می دهد مورد نیاز است. اجزای مختلف برنامه می توانند باعث شوند که فرآیند حاوی آن به طرق مختلف پیش زمینه در نظر گرفته شود. اگر یکی از شرایط زیر وجود داشته باشد، یک فرآیند در پیش زمینه در نظر گرفته می شود:
  2. فقط تعداد کمی از این فرآیندها در سیستم وجود دارد، و اینها تنها در صورتی از بین می روند که حافظه آنقدر کم باشد که حتی این فرآیندها نتوانند به کار خود ادامه دهند. به طور کلی، اگر این اتفاق بیفتد، دستگاه به حالت صفحه بندی حافظه رسیده است، بنابراین این عمل برای پاسخگو نگه داشتن رابط کاربری لازم است.

  3. یک فرآیند قابل مشاهده در حال انجام کاری است که کاربر در حال حاضر از آن آگاه است، بنابراین کشتن آن تأثیر منفی قابل توجهی بر تجربه کاربر دارد. یک فرآیند در شرایط زیر قابل مشاهده در نظر گرفته می شود:
    • در حال اجرای یک Activity است که روی صفحه برای کاربر قابل مشاهده است اما در پیش زمینه نیست (روش onPause() آن فراخوانی شده است). این ممکن است رخ دهد، برای مثال، اگر Activity پیش زمینه به عنوان یک گفتگو نمایش داده شود که اجازه می دهد Activity قبلی در پشت آن دیده شود.
    • Service دارد که به عنوان یک سرویس پیش‌زمینه از طریق Service.startForeground() اجرا می‌شود (که از سیستم می‌خواهد سرویس را به‌عنوان چیزی که کاربر از آن آگاه است یا اساساً به گونه‌ای که گویی قابل مشاهده است در نظر بگیرد).
    • میزبان سرویسی است که سیستم از آن برای ویژگی خاصی که کاربر از آن آگاه است استفاده می کند، مانند تصویر زمینه زنده یا سرویس روش ورودی.

    تعداد این فرآیندهای در حال اجرا در سیستم نسبت به فرآیندهای پیش زمینه محدودتر است، اما هنوز نسبتاً کنترل شده است. این فرآیندها بسیار مهم در نظر گرفته می‌شوند و از بین نمی‌روند، مگر اینکه انجام این کار برای اجرای تمام فرآیندهای پیش‌زمینه لازم باشد.

  4. یک فرآیند سرویس ، نگهداری Service است که با متد startService() شروع شده است. اگرچه این فرآیندها مستقیماً برای کاربر قابل مشاهده نیستند، اما معمولاً کارهایی را انجام می دهند که کاربر به آنها اهمیت می دهد (مانند بارگذاری یا دانلود داده های شبکه پس زمینه)، بنابراین سیستم همیشه چنین فرآیندهایی را در حال اجرا نگه می دارد، مگر اینکه حافظه کافی برای حفظ تمام پیش زمینه وجود نداشته باشد. و فرآیندهای قابل مشاهده

    خدماتی که برای مدت طولانی اجرا شده اند (مانند 30 دقیقه یا بیشتر) ممکن است از نظر اهمیت کاهش یابد تا روند آنها به لیست ذخیره شده کاهش یابد.

    فرآیندهایی که نیاز به اجرای طولانی مدت دارند را می توان با setForeground ایجاد کرد. اگر یک فرآیند دوره ای است که به زمان دقیق اجرا نیاز دارد، می توان آن را از طریق AlarmManager برنامه ریزی کرد. برای اطلاعات بیشتر، به پشتیبانی از کارگران طولانی مدت مراجعه کنید. این به جلوگیری از موقعیت‌هایی کمک می‌کند که سرویس‌های طولانی‌مدت که از منابع بیش از حد استفاده می‌کنند، به عنوان مثال، با نشت حافظه، مانع از ارائه یک تجربه کاربری خوب توسط سیستم می‌شوند.

  5. یک فرآیند ذخیره شده در حافظه پنهان، فرآیندی است که در حال حاضر مورد نیاز نیست، بنابراین سیستم آزاد است تا زمانی که منابعی مانند حافظه در جاهای دیگر مورد نیاز است، آن را در صورت نیاز از بین ببرد. در یک سیستم با رفتار عادی، اینها تنها فرآیندهایی هستند که در مدیریت منابع دخیل هستند.

    سیستمی که به خوبی اجرا می‌شود، چندین فرآیند ذخیره‌سازی شده را همیشه در دسترس دارد، برای جابه‌جایی کارآمد بین برنامه‌ها، و به طور منظم برنامه‌های ذخیره‌شده را در صورت نیاز از بین می‌برد. فقط در شرایط بسیار بحرانی سیستم به نقطه‌ای می‌رسد که تمام فرآیندهای حافظه پنهان کشته می‌شوند و باید شروع به کشتن فرآیندهای سرویس کند.

    از آنجایی که فرآیندهای ذخیره شده در حافظه پنهان می توانند در هر زمان توسط سیستم از بین بروند، برنامه ها باید در حالت ذخیره سازی کار خود را متوقف کنند. اگر برنامه باید کار حیاتی کاربر را انجام دهد، باید از APIهای بالا برای اجرای کار از حالت فرآیند فعال استفاده کند.

    فرآیندهای ذخیره شده در حافظه پنهان اغلب دارای یک یا چند نمونه Activity هستند که در حال حاضر برای کاربر قابل مشاهده نیستند (روش onStop() آنها فراخوانی شده و برگردانده شده است). به شرطی که چرخه حیات Activity خود را به درستی در زمانی که سیستم چنین فرآیندهایی را از بین می برد، پیاده سازی کنند، بر تجربه کاربر هنگام بازگشت به آن برنامه تأثیری نخواهد داشت. هنگامی که فعالیت مرتبط در یک فرآیند جدید دوباره ایجاد می شود، می تواند حالت ذخیره شده قبلی را بازیابی کند. توجه داشته باشید که onDestroy() تضمینی برای فراخوانی در مواردی که یک فرآیند توسط سیستم از بین می‌رود، وجود ندارد. برای جزئیات بیشتر، به Activity مراجعه کنید.

    با شروع در Android 13، یک فرآیند برنامه ممکن است تا زمانی که وارد یکی از حالت‌های چرخه حیات فعال بالا شود، زمان اجرا محدود یا بدون آن را دریافت کند.

    فرآیندهای ذخیره شده در حافظه پنهان در یک لیست نگهداری می شوند. خط مشی دقیق سفارش برای این لیست جزییات پیاده سازی پلتفرم است. به طور کلی، سعی می‌کند فرآیندهای مفیدتری مانند آن‌هایی که میزبان برنامه خانگی کاربر هستند یا آخرین فعالیتی که کاربر دیده است را قبل از سایر انواع فرآیندها حفظ کند. سیاست‌های دیگری برای از بین بردن فرآیندها نیز می‌تواند اعمال شود، مانند تعیین محدودیت‌های سخت برای تعداد فرآیندهای مجاز یا محدود کردن مدت زمانی که یک فرآیند می‌تواند به طور مداوم در حافظه پنهان بماند.

هنگام تصمیم گیری در مورد نحوه طبقه بندی یک فرآیند، سیستم تصمیم خود را بر اساس مهم ترین سطح موجود در بین تمام اجزای موجود در فرآیند استوار می کند. برای جزئیات بیشتر در مورد چگونگی کمک هر یک از این مؤلفه ها به چرخه عمر کلی یک فرآیند و برنامه، به مستندات Activity ، Service و BroadcastReceiver مراجعه کنید.

اولویت یک فرآیند نیز ممکن است بر اساس وابستگی های دیگری که یک فرآیند به آن دارد افزایش یابد. برای مثال، اگر فرآیند A به Service با پرچم Context.BIND_AUTO_CREATE متصل شده باشد یا از یک ContentProvider در فرآیند B استفاده می کند، طبقه بندی فرآیند B همیشه حداقل به اندازه فرآیند A مهم است.

،

در بیشتر موارد، هر برنامه اندرویدی در فرآیند لینوکس خود اجرا می شود. این فرآیند زمانی برای برنامه ایجاد می شود که برخی از کدهای آن باید اجرا شوند و تا زمانی که سیستم نیاز به بازیابی حافظه خود برای استفاده توسط سایر برنامه ها داشته باشد و دیگر نیازی به آن نباشد در حال اجرا باقی می ماند.

یکی از ویژگی‌های غیرعادی و اساسی اندروید این است که طول عمر یک برنامه کاربردی مستقیماً توسط خود برنامه کنترل نمی‌شود . در عوض، سیستم از طریق ترکیبی از بخش‌هایی از برنامه که سیستم می‌داند در حال اجرا هستند، تعیین می‌کند که این موارد چقدر برای کاربر مهم هستند و چه مقدار حافظه کلی در سیستم موجود است.

این مهم است که توسعه دهندگان برنامه بفهمند که چگونه مؤلفه های مختلف برنامه (به ویژه Activity ، Service و BroadcastReceiver ) بر طول عمر فرآیند برنامه تأثیر می گذارد. عدم استفاده صحیح از این مؤلفه‌ها می‌تواند منجر به از بین رفتن فرآیند برنامه در حین انجام کارهای مهم شود.

یک مثال متداول از یک اشکال چرخه حیات فرآیند، BroadcastReceiver است که وقتی یک Intent در متد BroadcastReceiver.onReceive() خود دریافت می کند، یک رشته را شروع می کند و سپس از تابع برمی گردد. پس از بازگشت، سیستم BroadcastReceiver را دیگر فعال نمی داند و فرآیند میزبانی آن دیگر مورد نیاز نیست، مگر اینکه سایر اجزای برنامه در آن فعال باشند.

بنابراین، سیستم می‌تواند در هر زمانی فرآیند را برای بازیابی حافظه از بین ببرد و با انجام این کار، نخ ایجاد شده در فرآیند را خاتمه می‌دهد. راه حل این مشکل معمولاً برنامه ریزی JobService از BroadcastReceiver است تا سیستم بداند که کار فعالی در این فرآیند در حال انجام است.

برای تعیین اینکه کدام فرآیندها در صورت کمبود حافظه حذف شوند، Android هر فرآیند را در یک سلسله مراتب اهمیت بر اساس مؤلفه های در حال اجرا در آنها و وضعیت آن مؤلفه ها قرار می دهد. به ترتیب اهمیت، این انواع فرآیند عبارتند از:

  1. فرآیند پیش زمینه فرآیندی است که برای کاری که کاربر در حال حاضر انجام می دهد مورد نیاز است. اجزای مختلف برنامه می توانند باعث شوند که فرآیند حاوی آن به طرق مختلف پیش زمینه در نظر گرفته شود. اگر یکی از شرایط زیر وجود داشته باشد، یک فرآیند در پیش زمینه در نظر گرفته می شود:
  2. فقط تعداد کمی از این فرآیندها در سیستم وجود دارد، و اینها تنها در صورتی از بین می روند که حافظه آنقدر کم باشد که حتی این فرآیندها نتوانند به کار خود ادامه دهند. به طور کلی، اگر این اتفاق بیفتد، دستگاه به حالت صفحه بندی حافظه رسیده است، بنابراین این عمل برای پاسخگو نگه داشتن رابط کاربری لازم است.

  3. یک فرآیند قابل مشاهده در حال انجام کاری است که کاربر در حال حاضر از آن آگاه است، بنابراین کشتن آن تأثیر منفی قابل توجهی بر تجربه کاربر دارد. یک فرآیند در شرایط زیر قابل مشاهده در نظر گرفته می شود:
    • در حال اجرای یک Activity است که روی صفحه برای کاربر قابل مشاهده است اما در پیش زمینه نیست (روش onPause() آن فراخوانی شده است). این ممکن است رخ دهد، برای مثال، اگر Activity پیش زمینه به عنوان یک گفتگو نمایش داده شود که اجازه می دهد Activity قبلی در پشت آن دیده شود.
    • Service دارد که به عنوان یک سرویس پیش‌زمینه از طریق Service.startForeground() اجرا می‌شود (که از سیستم می‌خواهد سرویس را به‌عنوان چیزی که کاربر از آن آگاه است یا اساساً به گونه‌ای که گویی قابل مشاهده است در نظر بگیرد).
    • میزبان سرویسی است که سیستم از آن برای ویژگی خاصی که کاربر از آن آگاه است استفاده می کند، مانند تصویر زمینه زنده یا سرویس روش ورودی.

    تعداد این فرآیندهای در حال اجرا در سیستم نسبت به فرآیندهای پیش زمینه محدودتر است، اما هنوز نسبتاً کنترل شده است. این فرآیندها بسیار مهم در نظر گرفته می‌شوند و از بین نمی‌روند، مگر اینکه انجام این کار برای اجرای تمام فرآیندهای پیش‌زمینه لازم باشد.

  4. یک فرآیند سرویس ، نگهداری Service است که با متد startService() شروع شده است. اگرچه این فرآیندها مستقیماً برای کاربر قابل مشاهده نیستند، اما معمولاً کارهایی را انجام می دهند که کاربر به آنها اهمیت می دهد (مانند بارگذاری یا دانلود داده های شبکه پس زمینه)، بنابراین سیستم همیشه چنین فرآیندهایی را در حال اجرا نگه می دارد، مگر اینکه حافظه کافی برای حفظ تمام پیش زمینه وجود نداشته باشد. و فرآیندهای قابل مشاهده

    خدماتی که برای مدت طولانی اجرا شده اند (مانند 30 دقیقه یا بیشتر) ممکن است از نظر اهمیت کاهش یابد تا روند آنها به لیست ذخیره شده کاهش یابد.

    فرآیندهایی که نیاز به اجرای طولانی مدت دارند را می توان با setForeground ایجاد کرد. اگر یک فرآیند دوره ای است که به زمان دقیق اجرا نیاز دارد، می توان آن را از طریق AlarmManager برنامه ریزی کرد. برای اطلاعات بیشتر، به پشتیبانی از کارگران طولانی مدت مراجعه کنید. این به جلوگیری از موقعیت‌هایی کمک می‌کند که سرویس‌های طولانی مدتی که از منابع بیش از حد استفاده می‌کنند، به عنوان مثال، با نشت حافظه، سیستم را از ارائه یک تجربه کاربری خوب باز می‌دارند.

  5. یک فرآیند ذخیره شده در حافظه پنهان، فرآیندی است که در حال حاضر مورد نیاز نیست، بنابراین سیستم آزاد است تا زمانی که منابعی مانند حافظه در جاهای دیگر مورد نیاز است، آن را در صورت نیاز از بین ببرد. در یک سیستم با رفتار عادی، اینها تنها فرآیندهایی هستند که در مدیریت منابع دخیل هستند.

    سیستمی که به خوبی اجرا می‌شود، چندین فرآیند ذخیره‌سازی شده را همیشه در دسترس دارد، برای جابه‌جایی کارآمد بین برنامه‌ها، و به طور منظم برنامه‌های کش شده را در صورت نیاز از بین می‌برد. فقط در شرایط بسیار بحرانی سیستم به نقطه‌ای می‌رسد که تمام فرآیندهای حافظه پنهان کشته می‌شوند و باید شروع به کشتن فرآیندهای سرویس کند.

    از آنجایی که فرآیندهای ذخیره شده در حافظه پنهان می توانند در هر زمان توسط سیستم از بین بروند، برنامه ها باید در حالت ذخیره سازی کار خود را متوقف کنند. اگر برنامه باید کار حیاتی کاربر را انجام دهد، باید از APIهای بالا برای اجرای کار از حالت فرآیند فعال استفاده کند.

    فرآیندهای ذخیره شده در حافظه پنهان اغلب دارای یک یا چند نمونه Activity هستند که در حال حاضر برای کاربر قابل مشاهده نیستند (روش onStop() آنها فراخوانی شده و برگردانده شده است). به شرطی که چرخه حیات Activity خود را به درستی در زمانی که سیستم چنین فرآیندهایی را از بین می برد، پیاده سازی کنند، بر تجربه کاربر هنگام بازگشت به آن برنامه تأثیری نخواهد داشت. هنگامی که فعالیت مرتبط در یک فرآیند جدید دوباره ایجاد می شود، می تواند حالت ذخیره شده قبلی را بازیابی کند. توجه داشته باشید که onDestroy() تضمینی برای فراخوانی در مواردی که یک فرآیند توسط سیستم از بین می‌رود، وجود ندارد. برای جزئیات بیشتر، به Activity مراجعه کنید.

    با شروع در Android 13، یک فرآیند برنامه ممکن است تا زمانی که وارد یکی از حالت‌های چرخه حیات فعال بالا شود، زمان اجرا محدود یا بدون آن را دریافت کند.

    فرآیندهای ذخیره شده در حافظه پنهان در یک لیست نگهداری می شوند. خط مشی دقیق سفارش برای این لیست جزییات پیاده سازی پلتفرم است. به طور کلی، سعی می‌کند فرآیندهای مفیدتری مانند آن‌هایی که میزبان برنامه خانگی کاربر هستند یا آخرین فعالیتی که کاربر دیده است را قبل از سایر انواع فرآیندها حفظ کند. سیاست‌های دیگری برای از بین بردن فرآیندها نیز می‌تواند اعمال شود، مانند تعیین محدودیت‌های سخت برای تعداد فرآیندهای مجاز یا محدود کردن مدت زمانی که یک فرآیند می‌تواند به طور مداوم در حافظه پنهان بماند.

هنگام تصمیم گیری در مورد نحوه طبقه بندی یک فرآیند، سیستم تصمیم خود را بر اساس مهم ترین سطح موجود در بین تمام اجزای موجود در فرآیند است. برای جزئیات بیشتر در مورد چگونگی کمک هر یک از این مؤلفه ها به چرخه عمر کلی یک فرآیند و برنامه، به مستندات Activity ، Service و BroadcastReceiver مراجعه کنید.

اولویت یک فرآیند نیز ممکن است بر اساس وابستگی های دیگری که یک فرآیند به آن دارد افزایش یابد. برای مثال، اگر فرآیند A به Service با پرچم Context.BIND_AUTO_CREATE متصل شده باشد یا از یک ContentProvider در فرآیند B استفاده می کند، طبقه بندی فرآیند B همیشه حداقل به اندازه فرآیند A مهم است.