安卓:进程与线程(进程篇)

进程和线程


快速预览

*组件指的是:安卓4大组件:Activity,Service,BroadCastReceiver,ContentProvider

· 任何应用程序运行于其所拥有的进程中,默认情况下,该程序的组件也运行在那个进程中。


· 任何缓慢的,阻塞的操作都应该新起一个线程,从而避免使用户觉得慢。


当一个应用程序组件启动,且应用程序无其他组件运行,安卓系统将开启一个新的Linux进程,而此进程中仅有单一的执行线程。默认情况下,同一应用程序的所有组件都运行于同一个进程和线程中(也叫主线程)。如果组件启动时,已经存在应用程序的组件进程了,那么组件将以那个进程启动,并使用相同的执行线程。然而,你可以安排不同的组件运行于独立的进程中,同时,你可以为任意进程创建额外的线程。


本文讨论了在一个安卓程序中,线程和进程如何工作。


进程


默认情况下,一个程序的所有组件将在一个进程下运行,并且大部分应用程序不应该更改它。然而,如果你发现你需要控制特定组件所属的进程,你可以在manifest 文件中这么做。


manifest条目对于每一个组件元素,如<activity><service><receiver>,<provider>都支持 android:process属性,你可以制定组件应该执行的进程。这样,你可以决定哪些在不同进程中,哪些在同一进程中。同样,你可以让不同的应用程序的组件运行在同一进程中,只要拥有相同Linux 用户ID和认证。


<application>元素也支持 android:process属性,用于设定所有组件所支持的默认值。


安卓可能会在某些情况下关闭一些进程,当内存较少而另外的进程需要立即为用户提供服务时。运行在进程中的应用程序组件被杀掉将会导致销毁(destroyed)。当他们再次工作时,进程将会再次启动这些组件。


当决定杀掉哪个进程时,安卓系统会衡量他们对于相关用户的重要性。举个例子,更有可能关闭不可见的activities 所对应的进程,而不是可见activities  所对应的进程。因此,决定关闭进程取决于组件运行的状态。用于决定进程被终结的规则可作如下讨论。


进程生命周期


安卓系统试图维持应用程序进程尽可能长,但最终还是要移除旧进程来为新的或者更重要的进程开辟内存空间。为了决定进程的留存或者销毁,系统将进程放置在“重要性分级”中,这基于运行在进程中的组件和他们的状态。拥有最低重要性的进程将会先被消灭,然后是次低的,以此类推,用于回收系统资源。

 

重要性分级存在5级。接下来的清单呈现了不同类型的进程,以重要性进行排序(第一个是最重要的,也是最后被杀死的)。


前台进程


用于相应用户当前操作的进程。一个进程被视为前台进程如果下面条件的任何一个为真。


·  它所持有的Activity 正与用户交互。(ActivityonResume()方法被调用)。

·  它所持有的Service绑定到正与用户交互的activity

·  它所持有的Service在前台运行——服务以调用startForeground().

·  它所持有的Service调用了以下三个回调函数之一:(onCreate()onStart(), or onDestroy()).

·  它所持有的BroadcastReceiver执行onReceive() 方法。


通常而言,在给定的时间下只有少数的前台进程得以保留。只有内存非常低时,他们才会被杀死。


通常,那也是因为设备到达内存换页状态,所以杀死前台进程也是为了用户交互请求的需要。


可见进程


一个进程没有任何前台组件,但他任然可以影响到用户在屏幕上所见。一个被视为“可见”,如果他满足如下几个之一。

 

·  其所持有的 Activity不在前台,但对于用户而言是可见的(onPause()方法被调用时)。这可能在这种情况下发生:如果前台activity 开启了一个对话框,之前的 activity在对话框后面,虽然它不再属于前台,但仍然可见。

·  它所持有的服务(Service )绑定了一个可见或者前台活动(activity)

 

可见进程被视为非常重要,除非为了前台进程运行,不然不会被杀死。


服务进程


服务进程运行一个以 startService()方法启动的服务,并且其不会进入之前提到的两个类别中的任意一个。尽管服务进程不会与用户所见的东西之间关联,但他们通常还是在做一些用户关心的事情(例如播放音乐已经下载数据),所以系统保证他们运行,除非这儿没有足够多的内存来维持前台进程或者可见进程的运作。


后台进程


后台进程持有用户当前不可见activity (也就是方法被调用)。这些进程对于用户体验没有任何直接影响,所以可在杀死他们来回收内存以供 前台、可见、服务进程使用。通常有很多后台程序运行,所以将他们放入LRU(最少最近使用)列表来保证最近用户所见activity 的进程最后被杀死。如果activity实现它自身生命周期的方法正确,并保持其当前状态,那么杀死进程将不会对用户体验产生任何影响,这是因为一旦用户导航到此activity ,其可见信息被恢复。查看Activities 文档以获得更多关于存储与恢复状态的信息。


空进程


进程未持有任何活动的应用程序组件。保留这种进程只有一个目的:缓存,从而在下次组件需要运行它的时候提高启动速度。系统经常杀死这些进程以在进程缓存和潜在的内核缓存中平衡全局系统资源。


安卓是基于当前活动进程中组件的重要性的,使用其中的最高级别来对进程进行排名。举个例子,如果一个进程拥有服务(service)和可见活动(activity),它将被以可见进程进行排名,而不是服务进程


额外说明的是,一个进程的排名可能上升,倘若其他进程依赖它的话——一个服务于其他进程的进程绝不会排名低于其服务的对象。举个例子,如果A内容提供者(content provider)将为进程B提供服务,或者A中服务绑定到B中组件,那么A的重要性至少等于B


由于运行服务的进程高于一个持有后台活动的进程,所以初始化长耗时操作的活动最好开启一个服务来进行那些操作,而不是简单的创建工作线程——尤其是那些可能比活动本身存在的时间更长的操作。举个例子,一个活动向网页上传一张图片应该开启一个服务来执行这个上传,这样即使用户离开了当前的activity,上传操作能够在后台继续执行。使用服务将使得进程至少具有“服务进程”优先级,而无论activity发生了什么。这对于广播接收者也是一样的道理,使用一个服务而不是简单将费时操作置于一个线程中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值