概述
在android系统中,每一个app都是一个linux的用户,默认情况下,每一个app都是运行在一个独立的进程中的一个单一线程里面的,这个线程称作主线程(main thread),UI的绘制就是在主线程里绘制的,所以这也就是许多android app的UI不流畅的根本原因所在。很显然,这种单一线程里面即处理UI绘制又处理业务逻辑的机制很容易导致UI绘制的丢帧现象,所以官方提供了android app进行多线程和多进程的编程方式。
android中的进程
android 中的进程与虚拟机
android 系统是基于 linux开发的,使用了linux系统用户的功能,每一个安装过的app都会被分配一个linux 的用户。默认情况下,当一个app启动后,android会为该app的用户创建一个进程(该进程是从Zygote进程fork出来的),app涉及到的所有的组件(比如Activity、Service、BroadcastReceiver等)都会在该进程中运行。
虽然在默认情况下系统会为每一个app创建一个独立的进程来执行它,但是,开发者也可以自己添加进程。android的四大组件Activity、Service、Reveiver、Provider在mainfest的配置文件中都有一个叫做 android:process 的属性值。开发者可以通过该属性值为对应的组件指定一个新的进程名称,系统会为该组件创建一个指定名称的进程。这样的话就实现了一个app包含有多个进程(它们是属于同一个linux用户的)。
另外一方面,android是使用java语言开发的,运行在JVM(之前是Dalvik,后来是ART)之上的程序。每一个app在启动后都会在一个独立的虚拟中运行,这样虽然比较耗资源,但是结果是更加安全。如上述,一个app可以包含多个进程,而每一个进程中都包含一个JVM(Dalvik/ART),所以一个app包含多个进程的话,它在运行的时候是启动了多个虚拟机的。
android 中进程间通信
android系统中提供了一个基于Binder机制的进程间通信技术(位于不同进程的Service间的通信就是基于该技术的)。
- 具体使用的话请参考AIDL。
- 想深入地了解android的 IPC技术的话,请参考老罗的文章Android进程间通信(IPC)机制Binder简要介绍和学习计划
android 中进程的优先级(在系统回收内存的时候)
android 会尽量让用户的进程在后台尽可能久地运行,但是当android 系统在意识到内存不够用的时候,为了保证用户的使用体验和系统的稳定运行,会选择性的回收内存,对进程来说,有些进程肯能会在系统的内存低的时候被回收掉。android 系统回收进程的时候会根据进程对当前用户操作的重要性来选择最不会影响到用户体验和系统稳定性的进程。
进程按重要性有高到低被分为以下这几类:
- 前台进程(Foreground Process)
- 可见进程(Visible Process)
- 服务进程(Service Process)
- 后台进程(Background Process)
- 空进程(Empty Process)
各个类型的进程的详情请参考官方文档,这里不再赘述。
注意:在开发的时候应考虑用户体验,不要把android提供的进程回收的优先级用到各种诸如“进程保活”这样的流氓行为上。app只需要做好自己的本职工作就好,无耻地在后台始终占据着系统资源对用户来说是很无耻的举动。
android 中进程与Task的关系
在该文章Activity 的 Task 以及 launchMode 研究中曾经研究过android的Task 和 Activity的launchMode,现在来考虑下android 中的进程和Task有什么关系?我们先来列一下他们各自的特点
- Task 是一个装有多个Activity实例的栈
- Task 是用户一系列的操作
- Task 对用户是可见的,也是面向用户的
- 一个Task中的Activity可以是来自多个Process的
- Process 是Activity运行的载体,负责管理Activity实例以及其他组件的内存
- Process 是属于某一个linux用户的,面向的是linux用户
那么,根据以上提到的点,我们可以发现Task 和 Process的联系是有一个层级关系的,他们之间的纽带是Activity实例。Process负责Activity的具体创建、内存管理、运行等,Task 是一个面向用户使用逻辑的一个抽象的栈结构。可以理解为Process为Task提供了物理层的依赖,Task是建立在Process基础之上的一个抽象的用户操作逻辑的封装。Task把Process的具体实现对用户隐藏了,只提供用户关系的部分。
在android中使用进程需要注意的问题
假如app使用了多个进程的话,那么必须要注意一下这些问题:
- 使用static关键字修饰的变量等将有可能在多个虚拟机中存在多份副本,在程序中使用的使用要注意这些变量的值将不会像只有单个进程的时候那样是“静态”的了。
- 每一个android的进程被创建的时候,android都会为该进程创建一个Application对象,所以,涉及到在Application对象中的操作要注意这个情况。
- 使用单例模式写的类,需要考虑到多进程的情况。
注意:因为多个进程带来的问题会比较多,所以在不是特别需要多个进程的时候,最好使用默认的但进程模式。
android中的线程
android 中的线程和Java中的是一样的,是一个独立的执行单元,一个进程中可以有多个线程执行。不像多进程之间,在多个线程之间是共享内存、cpu等硬件的,同样也共享JVM虚拟机的运行环境。使用多线程的编程可以避免上述的多进程可能存在的问题。默认情况下,一个app的所有组件都是运行在主线程(UI线程)中的,假如进行耗时或者阻塞的操作的话,应该开启子线程去进程操作。
参考资料:
https://developer.android.com/guide/components/processes-and-threads.html
http://blog.csdn.net/lynn0708/article/details/13624403