欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android进程优先级

程序员文章站 2024-03-23 15:07:52
...

Android 进程层次

Android进程优先级

前台进程(Foreground process)

前台进程是用户当前做的事所必须的进程,如果满足下面各种情况中的一种,一个进程被认为是在前台:

1.进程持有一个正在与用户交互的Activity

2.进程持有一个Service,这个Service至少满足这几种状况之一:
①Service与用户正在交互的Activity绑定。
②Service是在前台运行的,即它调用了 startForeground()
③Service正在执行它的生命周期回调函数(onCreate(), onStart(), or onDestroy())。

3.进程持有一个BroadcastReceiver,这个BroadcastReceiver正在执行它的 onReceive() 方法。

可见进程(Visible process)

如果一个进程不含有任何前台的组件,但仍可被用户在屏幕上所见。当满足如下任一条件时,进程被认为是可见的:

1.进程持有一个Activity,这个Activity不在前台,但是仍然被用户可见(处于onPause()调用后又没有调用onStop()的状态,比如,前台的activity打开了一个对话框,这样activity就会在其后可见)。

2.进程持有一个Service,这个Service和一个可见的(或者前台的)Activity绑定。

可见的进程也被认为是很重要的,一般不会被销毁,除非是为了保证所有前台进程的运行而不得不杀死可见进程的时候。

服务进程 (Service process)

如果一个进程中运行着一个service,这个service是通过 startService() 开启的,并且不属于上面两种较高优先级的情况,这个进程就是一个服务进程。

尽管服务进程没有和用户可以看到的东西绑定,但是它们一般在做的事情是用户关心的,比如后台播放音乐,后台下载数据等。所以系统会尽量维持它们的运行,除非系统内存不足以维持前台进程和可见进程的运行需要。

后台进程 (Background process)

如果进程不属于上面三种情况,但是进程持有一个用户不可见的activity(activity的onStop()被调用,但是onDestroy()没有调用的状态),就认为进程是一个后台进程。

后台进程不直接影响用户体验,系统会为了前台进程、可见进程、服务进程而任意杀死后台进程。

通常会有很多个后台进程存在,它们会被保存在一个LRU (least recently used)列表中,这样就可以确保用户最近使用的activity最后被销毁,即最先销毁时间最远的activity。

空进程 (Empty process)

如果一个进程不包含任何活跃的应用组件,则认为是空进程。

例如:一个进程当中已经没有数据在运行了,但是内存当中还为这个应用驻留了一个进程空间。
保存这种进程的唯一理由是为了缓存的需要,为了加快下次要启动这个进程中的组件时的启动时间。系统为了平衡进程缓存和底层内核缓存的资源,经常会杀死空进程。

注意事项:
当我们谈论进程优先级的时候是以 activity、service 这样的组件来说的,但请记住这些优先级是在进程的级别上,不是组件级别上。只要一个组件(比如一个前台服务)就会将整个进程变为前台进程。绝大多数应用是单进程的,如果你有生命周期差异很大的不同部分或者某个部分非常重量型,那么强烈建议你把它们分为不同的进程,让重量级进程尽早被回收。

Service中新开线程和直接新开线程的区别

若直接在Activity中新开一条线程来做耗时操作,当该Activity退出到桌面或其他情况时将成为一个后台进程
若在Service中新启动线程,则此时Android会依据进程中当前活跃组件重要程度,将其判断为服务进程,优先级比(1)高。

因为服务进程的优先级比后台进程的优先级高,所以对于一个需要启动一个长时间操作的activity来说,开启一个service比创建一个工作线程的方法更好,尤其是对于操作将很可能超出activity的持续时间时。

比如要上传一个图片文件,应该开启一个service来进行上传工作,这样在用户离开activity时工作仍在进行。使用service将会保证操作至少有服务进程的优先级。

尽可能保证Service不死常用技巧总结

1、在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = “1000”这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时实用于广播:

<service  
     android:name="com.dbjtech.acbxt.waiqin.UploadService"  
     android:enabled="true" >  
     <intent-filter android:priority="1000" >  
         <action android:name="com.dbjtech.myservice" />  
     </intent-filter>  
</service> 

2、在onStartCommand()里面调用 startForeground()把Service提升为前台进程级别,然后再onDestroy()里面要记得调用stopForeground ()方法。

3、onStartCommand()的返回值
onStartCommand(),返回的是一个int整形。
这个整形可以有以下四个取值:
1)START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
2)START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务
3)START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
4)START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。

4、在onDestroy()方法里发广播重启service。
service + broadcast 方式,就是当serviceonDestroy()的时候,发送一个自定义的广播,当收到广播的时候,重新启动service。(第三方应用或是在setting里-应用-强制停止时,APP进程就直接被干掉了,onDestroy()都进不来,所以无法保证会执行)

5、监听系统广播判断Service状态。
通过系统的一些广播,比如:手机重启、界面唤醒、应用状态改变等等监听并捕获到,然后判断我们的Service是否还存活。

6、Application加上Persistent属性。
加上以上属性相当于将该进程设置为常驻内存进程

比如系统phone中配置了android:persistent=”true”属性,并且Phone.apk是安装在/system/app/目录下的,所以在开机时会自动启动PhoneApp类。

切记,这个不可滥用,一般只适用于放在/system/app下的app,系统中用这个的service,app一多,整个系统可能就会崩溃。

参考:
1.生还是死?Android 进程优先级详解
2.Android开发之如何保证Service不被杀掉(broadcast+system/app)
3.Android基础总结——进程优先级及提高优先级的方法(Service尽量不死之法)