前言
首先我们需要了解什么是进程,进程和线程是两种完全不同的概念,从操作系统的角度来看,线程是CPU调度的最小单元,而进程一般指的是一个执行单元。在我们的Android系统中,一般一个进程指的是一个应用程序,但是不能说一个应用程序中只能有一个进程,一个应用程序中可以有多个进程,市面上主流的App,都是多进程的。一个进程中可以包含多个线程,因此进程和线程是包含与被包含的关系。在最简单的情况下,一个进程可以只有一个线程,即主线程,在Android里面主线程也叫UI线程,在UI线程里才能做更新UI界面操作。在主线程中是不允许进行耗时操作的,比如网络请求等等,因为那样会造成应用程序卡顿,可能导致应用程序ANR。为了避免ANR,我们一般都是把耗时操作放在子线程中进行。
为什么需要多进程
1. Android系统给单个应用可以使用的最大内存做了限制,有些app需要突破这个限制,想给应用程序获取更多的内存空间,那么可以通过多进程来获取更多的内存空间。
2. 有些特殊的模块需要不影响主模块的稳定性和占用主模块的内存。以及不受主业务进程生命周期影响,独立存在和运行。比如我们开发中常用的推送功能就需要使用多进程来实现。
3. app保活,有些app为了在后台运行时不被系统杀掉,往往会用多进程的方式来实现进程间互相监督,互相拉活来实现app保活。
多进程缺点
1. Application多次重建
2. 静态成员变量和单例模式完全失效
3. 线程同步机制完全失效
4. SharedPreferences可靠性降低
对于造成上面第三个问题的原因其实很简单,因为在多进程情况下,他们都不在同一块内存区域,那么不管是锁对象还是锁全局类都无法保证线程同步。因为不同进程锁的对象都不一样。静态变量和单例模式失效的原因就是因为系统为每个进程都单独分配了一个独立的虚拟机,这样就导致在不同的虚拟机中访问同一个类会产生多份副本。所以静态成员变量和单例模式自然也就失效了。对于SharedPreferences可靠性降低降低是因为SharedPreferences不支持两个进程同时对其进行操作。因为SharedPreferences的底层你先就是通过读写XML文件来实现的。并发的去读写肯定是会出问题的。
IPC
IPC不是Android系统上独有的,任何一个操作系统都需要相应的IPC机制来实现跨进程通信,window上面我们可以通过剪切板,管道等进行进程间通信,Linux中可以通过共享内存,信号量等来实现跨进程通信。 我们都知道Android系统是基于Linux开发的,但是它有自己的跨进程通信方式。
实现跨进程通信的几种方式
Android SDK给我们提供了比如 Activity,ContentProvider,Service,和BroadCast等几种方式。也可以通过Socket来实现跨进程通信。其中Activity可以跨进程调用其他应用程序的Activity;Content Provider可以跨进程访问其他应用程序中的数据(以Cursor对象形式返回),当然,也可以对其他应用程序的数据进行增、删、改操 作;Broadcast可以向Android系统中所有应用程序发送广播,而需要跨进程通讯的应用程序可以监听这些广播;Service和Content Provider类似,也可以访问其他应用程序中的数据,但不同的是,Content Provider返回的是Cursor对象,而Service返回的是Java对象,这种可以跨进程通讯的服务叫AIDL服务。
Activity方式
Activity的跨进程访问与进程内访问略有不同。虽然它们都需要Intent对象,但跨进程访问并不需要指定Context对象和Activity的 Class对象,而需要指定的是要访问的Activity所对应的Action(一个字符串)。有些Activity还需要指定一个Uri(通过 Intent构造方法的第2个参数指定)。比如我们在Android系统中有很多应用程序提供了可以跨进程访问的Activity,例如,下面的代码可以直接调用拨打电话的Activity。
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:87324443" );
startActivity(callIntent);
Content Provider
Android应用程序可以使用文件或SqlLite数据库来存储数据。Content Provider提供了一种在多个应用程序之间数据共享的方式(跨进程共享数据)。应用程序可以利用Content Provider完成增删改查。
虽然Content Provider也可以在同一个应用程序中被访问,但这么做并没有什么意义。Content Provider存在的目的向其他应用程序共享数据和在有条件的情况下允许其他应用程序对数据进行增、删、改操作。
Android系统本身提供了很多Content Provider,例如,音频、视频、联系人信息等等。我们可以通过这些Content Provider获得相关信息的列表。这些列表数据将以Cursor对象返回。因此,从Content Provider返回的数据是二维表的形式。
对于ContentProvider的使用方式可以参考这篇博客。
广播(Broadcast)
广播是一种被动跨进程通讯的方式。当某个程序向系统发送广播时,其他的应用程序只能被动地接收广播数据。这就象电台进行广播一样,听众只能被动地收听,而不能主动与电台进行沟通。在应用程序中发送广播比较简单。只需要调用sendBroadcast方法即可。该方法需要一个Intent对象。通过Intent对象可以发送需要广播的数据。