Android进程基本知识
当一个程序第一次启动的时候,Android会启动一个LINUX进程和一个主线程。默认的情况下,所有该程序的组件都将在该进程和线程中运行。
我们可以将一些组件运行在其他进程中,组件运行在哪个进程中是在manifest文件里设置的,其中,,和都有一个process属性来指定该组件运行在哪个进程之中。我们可以设置这个属性,使得每个组件运行在它们自己的进程中,或是几个组件共同享用一个进程,或是不共同享用。元素也有一个process属性,用来指定所有的组件的默认属性。
Android中的所有组件都在指定的进程中的主线程中实例化的,对组件的系统调用也是由主线程发出的。每个实例不会建立新的线程。对系统调用进行响应的方法——例如负责执行用户动作的View.onKeyDown()和组件的生命周期函数——都是运行在这个主线程中的。这意味着当系统调用这个组件时,这个组件不能长时间的阻塞主线程。例如进行网络操作时或是更新UI时,如果运行时间较长,就不能直接在主线程中运行,因为这样会阻塞这个进程中其他的组件,我们可以将这样的组件分配到新建的线程中或是其他的线程中运行。
Android进程级别
Android会根据进程中运行的组件类别以及组件的状态来判断该进程的重要性,Android会首先停止那些不重要的进程。按照重要性从高到低一共有五个级别:
1前台进程 2可见进程 3服务进程 4后台进程 5空进程
极端情况:内存不足的情况,会根据级别从低到高杀死进程
1)前台进程
前台进程是用户当前正在使用的进程。只有一些前台进程可以在任何时候都存在。如果有以下的情形的那么就是前台进程:
- 这个进程运行着一个正在和用户交互的Activity(这个Activity的onResume()方法被调用)。
- 这个进程里有绑定到当前正在和用户交互的确Activity的一个service。
- 这个进程里有一个service对象,这个service对象正在执行一个它的生命周期的回调函数(onCreate(), onStart(), onDestroy())
- 这个进程里有一个正在的onReceive()方法的BroadCastReiver对象。
2)可见进程
可见进程不包含前台的组件但是会在屏幕上显示一个可见的进程是的重要程度很高,除非前台进程需要获取它的资源,不然不会被中止。如果有如下的一种情形就是可见进程:
- 这个进程中含有一个不位于前台的Activity,但是仍然对用户是可见的(这个Activity的onPause()方法被调用),这是很可能发生的,例如,如果前台Activity是一个对话框的话,就会允许在它后面看到前一个Activity。
- 这个进程里有一个绑定到一个可见的Activity的Service。
3)服务进程
运行着一个通过startService() 方法启动的service,这个service不属于上面提到的2种更高重要性的。service所在的进程虽然对用户不是直接可见的,但是他们执行了用户非常关注的任务(比如播放mp3,从网络下载数据)。只要前台进程和可见进程有足够的内存,系统不会回收他们。
4)后台进程
运行着一个对用户不可见的activity(调用过 onStop() 方法).这些进程对用户体验没有直接的影响,可以在服务进程、可见进程、前台进 程需要内存的时候回收。通常,系统中会有很多不可见进程在运行,他们被保存在LRU (least recently used) 列表中,以便内存不足的时候被第一时间回收。如果一个activity正确的执行了它的生命周期,关闭这个进程对于用户体验没有太大的影响。
5)空进程
未运行任何程序组件。运行这些进程的唯一原因是作为一个缓存,缩短下次程序需要重新使用的启动时间。系统经常中止这些进程,这样可以调节程序缓存和系统缓存的平衡。
Android 对进程的重要性评级的时候,选取它最高的级别。例如,如果一个进程含有一个service和一个可视activity,进程将被归入一个可视进程而不是service进程。
提升进程级别
当被另外的一个进程依赖的时候,某个进程的级别可能会增高。一个为其他进程服务的进程永远不会比被服务的进程重要级低。
可以思考一个问题,当需要执行耗时操作时,到底使用子线程还是Service呢?
因为服务进程比后台activity进程重要级高,因此一个要进行耗时工作的activity最好启动一个service来做这个工作,而不是开启一个子进程——特别是这个操作需要的时间比activity存在的时间还要长的时候。例如,在后台播放音乐,向网上上传摄像头拍到的图片,使用service可以使进程最少获取到“服务进程”级别的重要级,而不用考虑activity目前是什么状态。broadcast receivers做费时的工作的时候,也应该启用一个服务而不是开一个线程。