android.jpg在大多数情况下,每个Android应用程序都在自己的Linux进程中运行。当需要运行某些代码时,将为应用程序创建此过程,并且该过程将一直运行,直到不再需要它为止,并且 系统需要回收其内存以供其他应用程序使用。
应用程序的生命周期不是由应用程序直接控制的
和大家想的不太一样,android的应用程序进程的生命周期并不是由它自己本身控制的。
它是由系统通过应用程序正在运行的程序中的组合,这些程序的组合对用户的重要性以及系统中可以用的总体内存量来决定的。
这些决定应用程序生命周期的组件就是我们的四大组件之三(Activity
,Service
,BroadcastReceiver
).
如果不正确的使用这些组件就会导致系统在运行重要工作是终止掉应用程序的进程。
一个常见的错误,在BroadcastReceiver.onReveive()
中开启新的线程。
经常被面试的时候问到,是否可以在BroadcastReceiver.onReceive()
开启新的线程来进行耗时的操作。
不可以。在BroadcastReceiver.onReceive()
方法收到广播,开启一个线程,接着它返回也就是执行完毕后,系统会认为BroadcastReceiver
不在处于活动状态。因此不在需要起托管进程(除非其他应用程序组件处于活动状态,如Activity
,Service
)。
因此系统可能随时终止进程来回收内存,并且这样会终止进程中运行的线程。
这个问题的解决方案是你可以开启一个Service
,然后在这个Service
里开启新的线程,来执行耗时的任务操作。而官网给的的答案是使用JobService
,需要翻墙
进程的分类
为了确定在内存不足时应该杀死哪些进程,Android
会根据其中运行的组件以及这些组件的状态来每一个进程分类。按重要性顺序依次分为:
1.前台进程
前台进程是当前程序正在和用户进行交互的进程。而各大组件用不同的方式让进程变为前台进程。如满足下面的条件,就是前台进程。
- 它正在和
Activity
进行交互的,在屏幕的顶端运行的,其onResume()
方法已经被调用 - 它有一个
BroadcastReceiver
当前正在运行的,即它的BroadcastReceiver.onReceive()
方法正在执行. - 它有一个
Service
当前正在回调其生命周期方法,如(Service.onCreate()
,Service.onStart()
,或Service.onDestroy()
)。
他们是优先级最高的进程,只有在内存太低或者这些进程都不能继续运行的时候,才会作为最后的手段被杀死。因为这个时候,设备已达到内存分页状态,需要此操作来保持用户界面的响应。
2.可见进程
可见进程就是用户当前可以看到,但是无法与其交互,并不是处于最顶端的进程,杀死它会造成非常恶劣的影响。如果满足下面的条件,就是前台进程。
- 它运行的
Activity
是屏幕上用户可见但并不在前台,其onPause()
方法已经被调用。 - 它有一个
Service
作为前台服务运行的,通过调用Service.startForeground()
方法。通过要求系统将服务视为用户知道的,或者是对他们基本可见的东西。 - 它正在托管系统用于用户知道的特定功能的服务,例如动态壁纸,输入法服务等。
在系统中可见进程要比前台进程更少,但是其同样是受控的。这些进程被系统认为非常重要,除非需要杀死这些进程以保持前台进程的运行,否则不会被杀死。
3.服务进程
服务进程就是一个进程里面运行了服务的进程。里面有一个服务是通过startService
方法开启的。
虽然用户无法看到这些进程,但是他们通常是用户关心的,例如后台网络数据的上传和下载。因此系统将始终保持此类进程的运行,除非没有足够的内存来保留可见进程和前台进程的运行。
如果该服务进程运行了很长时间(例如30分钟或者更长时间),那么服务可能会降级,以允许其进程下降到下面描述的缓存LRU
列表。这有助于避免出现内存泄漏或其他问题的长时间运行服务占用大量RAM
而导致系统无法有效使用缓存进程的情况。
4.缓冲进程
缓冲进程就是并不是上面的情况,处于后台运行,一个当前没有必要保留的进程。因此系统会根据内存的需要把它杀死来腾出内存空间。
在正常运行的系统中,这些是内存管理中唯一涉及的进程。
运行良好的系统会始终保持多个缓冲进程(用于在应用程序之间更加有效的切换),并根据需要定期终止最旧的进程,只有在非常关键且并不可取的情况下,系统才会到达杀死所有缓冲进程的点,并且必须会开始终止服务进程。
这些进程通常包含一个或多个Activity
当前对用户不可见的实例(该 onStop()
方法已被调用并返回)。如果他们正确地实现了他们的活动生命周期(参见Activity
更多细节),当系统杀死这样的过程时,它不会影响用户返回该应用程序时的体验:它可以在相关活动重新创建时恢复以前保存的状态。新进程。
这些进程保存在伪LRU
列表中,列表中的最后一个进程就是第一个被系统回收的进程。
如何进行进程保活
那么这里就涉及到了如何系统保护的问题?
在我们上面的可以看到,可见进程都不安全,有可能被系统杀死,当然这是属于极端的情况。
进程保活的思路其实就是让其进程是可见进程或者是前台进程。
当进程正在运行的时候,我们当然不必担心这个情况。可是当应用程序处于后端的时候,就有了被杀死的风险,所以我们需要让它始终处于前台进程或者是可见进程。
1.创建一个Activity
,让其始终处于前端,我们可以把它的主题设置为透明,宽高都只有一个像素,让其处于左上角,这样程序退出后并不是真的退出,而是有一个Activity
始终处于前台。
2.设置可见进程,通过Service.Service.startForeground()
方法。
3.通过一个隐藏的通知栏,让这个通知栏始终存在。
为什么我们需要Service
?
当我们在Activity
里开启一个新的线程,然后在这个线程里异步的进行一个耗时的操作,我们同样可以达到目的,为什么还需要Service
呢?
因为这个时候我们的应用程序一旦被切换到后台,那么它就处于缓冲进程进程。系统杀死它不会造成恶劣的影响,为了使我们的应用程序保活,使其应用程序处于更高的优先级。
我们就让它成为服务进程。在Service
里面进行耗时的操作,这样可以免除被杀死的恶果。
网友评论