进程和应用程序生命周期

https://developer.android.google.cn/guide/components/activities/process-lifecycle.html

在大多数情况下,每个Android应用程序都在自己的Linux进程中运行。当应用程序的一些代码需要运行时,系统为应用程序创建这个进程,并且将继续运行直到不再需要它,系统需要回收它的内存以供其他应用程序使用。

Android的一个不同寻常的基本特性是,应用程序的生命周期不是由应用程序本身直接控制的。相反,系统通过系统知道的正在运行的应用程序的各个部分的组合,这些东西对用户有多重要,以及系统中有多少可用内存来决定进程的生命周期。

应用程序开发人员了解不同的应用程序组件(特别是activity、服务和广播接收器)如何影响应用程序进程的存在期,这一点非常重要。不正确使用这些组件会导致系统在执行重要工作时杀死应用程序的进程。

进程生命周期错误的一个常见的例子是BroadcastReceiver在BroadcastReceiver.onReceive()方法中收到一个intent时启动一个线程,然后从该函数返回。一旦它返回,系统就会认为广播接收器不再活动,因此不再需要它的托管进程(除非其他应用程序组件在其中活动)。因此,系统可能随时终止进程以回收内存,并在此过程中终止运行在进程中的派生线程。这个问题的解决方案通常是在广播接收器中安排一个JobService,这样系统知道在这个过程中仍然有工作正在进行。

为了确定在内存不足时应该杀死哪些进程,Android将每个进程置于一个“重要性层次结构”中,这个结构基于它们运行的组件和这些组件的状态。这些进程类型(按重要性排序):

  •  前台进程是用户当前正在做的事情。各种应用程序组件可以以不同的方式使包含它的进程被视为前台进程。如果有下列条件之一,则认为进程处于前台:
    • 它在用户正在与之交互的屏幕顶部运行一个activity(它的onResume()方法已被调用)。
    • 它有一个BroadcastReceiver目前运行(其BroadcastReceiver.onReceive()方法执行)。
    • 它有一个当前在其回调函数中执行代码的服务(Service. oncreate()、Service. onstart()或Service. ondestroy())。

在系统中只会有一些这样的进程,如果内存太低,甚至这些进程都无法继续运行,那么这些进程将会作为最后的手段被杀死。通常,在这一点上,设备已经达到内存分页状态,因此需要采取这种操作,以保持用户界面的响应。

  • 可见进程 正在做用户目前知道的工作,所以杀死它会对用户体验产生明显的负面影响。在以下条件下,进程被认为是可见的:
    • 它运行的activity是在屏幕上可见的,但不是在前台(它的onPause()方法被调用)。例如,如果前台activity显示为一个对话框,能在它后面看到之前的activity,则可能会出现这种情况。
    • 它有一个通过 Service.startForeground()(它要求系统将服务视为用户知道的东西,或者从本质上来说是可见的) 作为前台服务运行的服务。
    • 它正在托管一个服务,系统使用该服务执行用户所知道的特定功能,如实时壁纸、输入方法服务等。

系统中运行的这些进程的数量比前台进程的限制少,但仍然相对可控。这些进程被认为是非常重要的,不会被杀死除非这样做是为了保证前台进程运行。

  • 服务进程是一个包含了使用startService()方法启动的服务的进程。虽然这些过程对用户来说不是直接可见的,但是他们通常都在做用户关心的事情(比如后台网络数据上传或下载),所以系统将始终保持这样的进程,除非没有足够的内存来保留所有前台和可见的进程。

已经运行了很长时间(比如30分钟或更长时间)的服务可能会被降级,从而允许它们的进程被降到接下来描述的缓存的LRU列表中。这有助于避免长时间运行的服务由于内存泄漏或其他问题占用大量内存而导致系统无法有效使用缓存进程的情况。

  • 缓存的进程是当前不需要的,因此当需要其他地方需要内存时,系统可以随意地杀死它。在正常运行的系统中,这些是涉及内存管理的唯一进程:一个运行良好的系统将会有多个始终可用的缓存的进程(以便在应用程序之间进行更有效的切换),并根据需要定期杀死最老的进程。只有在非常临界的(且不受欢迎)的情况下,系统才会到达杀死所有缓存进程的点,并且它必须开始杀死服务进程。

这些进程通常包含一个或多个用户不可见的activity实例(onStop()方法已被调用并返回)。如果他们正确地实现了activity生命周期,当系统杀死这些过程时,它不会影响用户返回到该应用程序时的体验:当关联的activity在一个新进程中重新创建时,它可以恢复先前保存的状态。

这些进程被保存在一个伪lru列表中,其中列表的最后一个进程是第一个被杀死的以回收内存的进程。在这个列表上排序的确切策略由平台来实现细节,但是通常它会保留更多有用的进程(托管了用户的主页的进程,用户看见的最后一个activity,等等)而不是其他类型的进程。其他用于杀死进程的策略也会应用:对允许的进程数量的严格限制,对进程可以持续缓存的时间的限制等。

在决定如何对流程进行分类时,系统将根据在进程中当前activity的所有组件中发现的最重要的级别来决定。

一个进程的优先级也可以根据进程对它的依赖程度来增加。例如,如果进程A使用Context.BIND_AUTO_CREATE标志绑定到一个服务,或使用了一个在进程B中的ContentProvider,那么进程B的分类将总是和进程A一样重要。

 

posted @ 2018-03-16 17:00  caroline2016  阅读(231)  评论(0编辑  收藏  举报