Android 进程和应用的生命周期

进程和应用的生命周期

多数情况下,应用运行在他自己的Linux进程里。当需要运行代码时,系统为应用程序分配一个进程,应用一直运行在该进程里,一直到不再需要了,系统重新收回这部分内存供其它应用使用。

Android中一个特殊的地方在于应用进程的生命周期不完全由应用自己控制。而是系统通过正在运行的所有应用经过整合,例如该应用对用户来说有多重要,还剩多少内存等决定应用的生命周期。

直到每个组件(Activity,Service,BroadcastReceiver,Contentprovider)是如何影响应用生命周期很重要。组件的错误使用可能引起系统杀死正在执行重要代码的应用进程。

一个进程生命周期典型的bug就是BroadcastReceiver在他的onReceive()方法中收到一个intent,然后启动一个线程执行任务,然后返回。一旦返回,系统就认为BroadcastReceiver已经不再需要,他所在的进程也不需要了(除非进程里还有其它应用组件)。所以,系统随时可能收回进程,释放内存,同时把进程里的线程也关掉了。解决办法就是启动一个JobService,这样系统知道进程里还有活动的工作。

低内存时杀掉哪个应用,Android基于组件及其状态把每个进程都划分了重要性优先级。进程优先级有:

1、前台进程是用户正在使用的进程。各种组件都能以不同的方式使其所在进程成为前台进程。下面任何一种情况都是进程进入前台进程:

  • 用户正在交互的显示在屏幕最上方的Activity(onResume()方法被调用了)。
  • BroadcastReceiver正在运行(BroadcastReceiver.onReceive()方法正在执行)。
  • Service正在执行回调(Service.onCreate(),Service.onStart()或者Service.onDestroy())。

这种进程只会存在几个,如果内存低,他们会最后被杀掉。这种情况下,一般存储器正在执行换页操作,以保证设备和用户交互。

2、可见进程执行的工作对用户来说是可感知的,所以如果杀掉这种进程,会产生不好的用户体验。下面几种情况属于可见进程。

  • 程序正在运行Activity,Activity可见但不在前台(onPause()已经被调用)。例如,前台应用显示为Dialog,Dialog后面的Activity所在的进程即为可见进程。
  • 通过Service.startForegroundService()启动的服务,服务正在运行的进程。
  • 用户可感知的特殊服务正在使用的服务所在的进程,例如动态壁纸,输入法服务等。

这种进程的数量比前台进程控制的少些,但是也是有所控制的。这些进程被认为是很重要的进程,一般不会被杀,除非前台进程不能运行了。

3、服务进程中有一个通过startSerivce()调用起来的服务。尽管这些进程用户不可见,但是他们执行一些对用户来说很重要的任务(后台上传,下载数据),系统会一直保持这些进程,除非前台进程和可见进程不能执行了。

运行了很长时间(30分钟)的服务重要性可能会被降级,降到的缓冲进程。这样可以避免一些长期运行的服务,带有内存泄露或者其他问题,消耗了太多内存,使得缓冲进程的效果变差。

4、缓冲进程即不再需要的进程,如果其他地方需要内存,系统随时可以回收他们。在一个正常行为系统中,这种进程是包含在内存管理中的进程:一个好的运行系统总是有多个缓冲进程(为了更有效的在进程之间切换)并定期杀掉最老的缓冲进程。只有在非常严重(不方便)的时候,才会杀掉所有缓冲进程,并且开始杀服务进程。

这些进程通常持有一个或多个用户不可见(onStop()方法已经被调用并返回)的Activity实例。假如正确实现了Activity的生命周期,系统杀掉该进程并不会影响到用户体验。当用户重新进入该应用时:在新的进程中重新创建时,Activity可以恢复之前保存的状态。

这些进程保存在伪LRU列表中,列表中最后的进程是回收内存最先被杀掉的。具体实现是在平台中,但是总的来说,测略是保护更加重要的进程(一个保存home应用,最早看到的Activity)。其它杀进程策略同样适用:进程数量,进程在缓冲区最长时间等。

当决定进程的重要性时,系统根据最重要的组件决定其所在进程的重要级别。各组件文档中更加详细的描述了其对进程重要性的影响。

如果其他进程依赖该进程,被依赖的进程重要性有可能会被提高。例如,进程A通过Context.BIND_AUTO_START绑定一个B进程的服务或者用B进程的ContentProvider,那么B进程优先级不低于A。

猜你喜欢

转载自blog.csdn.net/yubing1015/article/details/85264899