概要

  • 多进程概念及多进程常见注意事项
  • IPC基础:Android序列化和Binder
  • 跨进程常见的几种通信方式:Bundle通过Intent传递数据,文件共享,ContentProvider,基于Binder的AIDL和Messenger以及Socket。
  • Binder连接池
  • 各种进程间通信方式的优缺点及适用场景

IPC是 Inter-Process Communication的缩写,意为进程间通信跨进程通信,是指两个进程之间进行数据交换的过程。

线程是CPU调度的最小单元,同时线程是一种有限的系统资源。进程一般指一个执行单元,在PC和移动设备上指一个程序或者一个应用。一个进程可以包含多个线程,因此进程和线程是包含与被包含的关系。最简单的情况下,一个进程中只可以有一个线程,即主线程,在Android中也叫UI线程。

IPC不是Android中所独有的,任何一个操作系统都需要相应的IPC机制,比如Windows上可以通过剪贴板等来进行进程间通信。Android是一种基于Linux内核的移动操作系统,它的进程间通信方式并不能完全继承自Linux,它有自己的进程间通信方式。

    1. Android中的多进程模式

通过给四大组件指定android:processs属性可以开启多进程模式,我们无法给一个线程或一个实体类指定其运行所在的进程。

<activity
android:name=".SecondActivity"
android:process=":remote"/>
<activity
android:name=".ThirdActivity"
android:process="com.example.remote"/>

应用默认的进程是当前包名,以上分别给两个Activity指定了进程,意味着当前应用又增加了两个新进程。假设当前应用包名为com.ipc.example,那么SecondActivity所在的进程为com.ipc.example.remote,“:”的含义是要在当前进程名前面附上当前的包名,而且已“:”开头的进程属于当前应用的私有进程,其他应用的组件不可以和它跑在同一进程。不以“:”开头的进程是全局进程,如指定了ThirdActivity所在的进程为全局进程。

 2.  多进程模式的运行机制

新建UserManager类:

public class UserManager {
public static int sUserId = 1;
}

在MainActivity中将sUserId的值修改为2,由于MainActivity在应用默认进程,SecondActivity在指定进程,在SecondActivity中打印sUserId的值会发现sUserId值并没有变,还是1。

出现这样的原因是SecondActivity运行在单独的进程,Android为每个应用分配了一个独立的虚拟机或者说为每个进程都分配了一个独立的虚拟机,不同的虚拟机在内存上都有不同的地址空间,这就导致在不同的虚拟机中访问同一个对象会产生多分副本。上面示例中MainActivity修改了sUserId的值只会影响当前进程,对其他进程不会造成 任何影响。

所有运行在不同进程的四大组件,只要它们之间需要通过内存来共享数据都会失败。一般来说多进程会造成以下几个问题:

  • 静态成员和单例模式完全失效
  • 线程同步机制完全失效(不在同一进程,,锁的不是同一对象,所以不管锁对象还是锁全局类都无法保证线程同步)
  • SharePreferences的可靠性下降
  • Application会多次创建(在Application的onCreate()中打印当前进程名证实了同一应用不同进程下,Application会多次创建。这也说明了多进程模式下,不同进程的组件的确会拥有独立的虚拟机、Application以及内存空间)

 3. Serializable和Parcelable接口

Serializable和Parcelable可以完成对象的序列化过程,当我们需要通过Intent和Binder传输数据时就需要进行序列化,Serializable是Java提供的一个空接口,为对象提供标准的序列化和反序列化操作。使用简单但是序列化和反序列都会做大量的I/O读写操作,内存开销较大。

Parcelable是Android中的序列化方式,使用稍微复杂,但是效率高。

 4.  Android中的IPC方式:

     4.1: 使用Bundle

四大组件中的其中三个(Activity、Service、Receiver)都是支持在Intent中传递Bundle数据,由于Bundle实现了Parcelable接口,所以它可以方便的在不同进程间传输。

     4.2:使用文件共享

文件共享也是一种不错的进程间通信方式,两个进程通过读写同一个文件来交换数据,比如A进程中把数据写入文件,B进程通过读取这个文件来获取数据。但是这种方式也是又一定局限性的,比如并发读写的问题会导致我们读出的数据不是最新的,因此要避免并发读写的发生或者考虑使用线程同步来限制多个线程的读写操作。基于这样的问题,文件共享方式适合对数据同步要求不高的进程之间进行通信。

4.3:使用Messenger

Messenger是一种轻量级的IPC方案,它的底层实现是AIDL,通过Messenger可以在不同进程中传递Message对象,在Message中放入我们需要传递的数据就可以轻松实现数据在进程间传递了。

Messenger的使用很简单,由于它一次处理一个请求,因此在服务端不用考虑线程同步的问题。Messenger实现进程间通信大致可以分为以下几步,分为服务端和客户端。

  • 服务端进程
    首先需要在服务端新建一个Service来处理客户端发起的请求,同时创建一个Handler并通过它来创建一个Messenger对象,然后在Service的onBind中返回这个Messenger对象底层的Binder即可。
  • 客户端进程
    客户端进程中首先要绑定服务端的Service,绑定成功后用服务端返回的IBinder对象创建一个Messenger,通过这个Messenger就可以向服务端发送类型为Message的消息了。

注册Service,使其运行在单独的进程,AndroidManifest.xml中配置:

Log日志:

在Messenger中进行数据传递必须将数据放入Message中,而Messenger和Message都实现了Parcelable接口,因此可以跨进程传输。上面的实例只是介绍了如何在服务端接受客户端中发送的请求,但是有时候还需要回应客户端。每当客户端发来一条消息,服务端就自动回复一条“来自服务端的自动回复:消息已收到”。如果需要客服端能够回应客户端,那么和服务端一样,在客户端还需要创建一个新的Messenger,并把这个Messenger对象通过Message的replyTo参数传递给服务端,服务端通过这个replyTo参数就可以回应客户端。

修改后的服务端代码:

        

修改后的客户端代码:

       

4.4: 使用AIDL

Messenger是以串行的方式处理客户端的请求,如果有大量的请求同时发送到服务端,服务端仍然只能一个一个处理,此时Messenger就不大合适了,同时Messenger的作用是为了传递消息,且只能传递Bundle支持的数据类型,很多时候需要跨进程调用服务端的方法,这时候可以实用AIDL来实现跨进程的方法调用。AIDL也是Messenger的底层实现,因此Messenger本质上也是AIDL,只不过系统作了封装。实用AIDL进行进程间通信的流程分为服务端和客户端两个方面,下面分别介绍:

    • 服务端
      服务端首先要创建一个Service用来监听客户端的连接请求,然后创建一个AIDL文件将暴露给客户端的接口在这个AIDL文件中声明,最后在Service中实现这个AIDL接口即可
    • 客户端
      客户端要做的事情稍微简单些,首先绑定服务端的Service,绑定成功后将服务端返回的Binder对象转成AIDL接口所属的类型,接着就可以调用AIDL中的方法了
    • AIDL接口的创建
      详情参考:https://www.zhihu.com/question/21581761

      需要注意的是,如果AIDL文件中用到了自定义的Parcelable对象,那么必须新建一个和它同名的AIDL文件,并在其中声明为Parcelable类型。上面代码中我们用到了BookEntity这个类,所以必须创建BookEntity.aidl,然后将BookEntity定义为Parcelable类型。

    • 服务端的实现


运行在独立进程:

<service
android:name=".service.BookManagerService"
android:process="com.ipc.example.remote"/>
  • 客户端实现

这是一次完整的使用AIDL实现进程间通信,但是远远还没有完,AIDL的复杂性远不止这些。下一篇着重总结AIDL的使用。

Android IPC机制全解析<一>的更多相关文章

  1. Android IPC机制全解析<二>

    在AIDL文件中并不是所有的数据类型都可以使用,AIDL支持的数据类型如下: 基本数据类型(int.long.char.boolean.double等) String和CharSequence Lis ...

  2. Android异步载入全解析之使用多线程

    异步载入之使用多线程 初次尝试 异步.异步,事实上说白了就是多任务处理.也就是多线程执行.多线程那就会有各种问题,我们一步步来看.首先.我们创建一个class--ImageLoaderWithoutC ...

  3. Android异步载入全解析之IntentService

    Android异步载入全解析之IntentService 搞什么IntentService 前面我们说了那么多,异步处理都使用钦定的AsyncTask.再不济也使用的Thread,那么这个Intent ...

  4. Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用

    在上一篇文章Android IPC机制(二)用Messenger进行进程间通信中我们介绍了使用Messenger来进行进程间通信的方法.可是我们能发现Messenger是以串行的方式来处理client ...

  5. Android异步载入全解析之大图处理

    Android异步载入全解析之大图处理 异步载入中很重要的一部分就是对图像的处理,这也是我们前面用异步载入图像做示例的原因. 一方面是由于图像处理不好的话会很占内存,并且easyOOM,还有一方面,图 ...

  6. Android异步载入全解析之使用AsyncTask

    Android异步载入全解析之使用AsyncTask 概述 既然前面提到了多线程,就不得不提到线程池,通过线程池,不仅能够对并发线程进行管理.更能够提高他们运行的效率.优化整个App.当然我们能够自己 ...

  7. 深入理解Android IPC机制之Binder机制

    Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥有的进程间通信IPC手段包括(Internet Process Connection): 管道(Pipe).信号(Sign ...

  8. android IPC 机制 (开发艺术探索)

    一.IPC 机制介绍 IPC是Inter-Process Communication的缩写,含义就是进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程.那么什么是进程,什么是线程,进程和线程 ...

  9. Handler消息机制与Binder IPC机制完全解析

    1.Handler消息机制 序列 文章 0 Android消息机制-Handler(framework篇) 1 Android消息机制-Handler(native篇) 2 Android消息机制-H ...

随机推荐

  1. 自行搭建私有云ownCloud,启用SSL,其他配置

    ownCloud简介 ownCloud(官网)是一款开源的私有云框架,可以通过它实现个人网盘的功能,如果拥有一个性能不错的VPS,那么就可以摆脱奇慢无比的百度云等网盘啦!我花了大约一天的时间总算搭好了 ...

  2. 【openstack N版】——网络服务neutron

    一.openstack网络服务neutron 1.1neutron介绍 neutron是openstack重要组件之一,在以前是时候没有neutron项目,早期的时候是没有neutron,早期所使用的 ...

  3. SUN SERVER X3-2 服务器数据写入缓慢

    使用一台sun server x3-2,SAS 300G 2.5寸硬盘两块:8G内存条*2,CPU E5-2609V3 安装一套服务器系统时感觉安装进度很慢,但一直找不到原因,因为要重做系统,同事练手 ...

  4. 每天一个Linux命令(12)--more命令

    more命令,功能类似cat,  cat 命令是这个文件的内容从上到下显示在屏幕上,more会以一页一页的显示方便使用者主页阅读,而最基本的指令就是按空格键就往下一页显示,按B键就会往回一页显示,而且 ...

  5. SQL语句使用时间和日期的函数

    getdate():获取系统当前时间dateadd(datepart,number,date):计算在一个时间的基础上增加一个时间后的新时间值,比如:dateadd(yy,30,getdate())d ...

  6. 解决clipboard手机端无法复制的一种思路

    最近,做了一个切图的小项目 主要内容是微信号的推广页面,上面会有精美的图片和微信号:) 点击按钮,会复制到粘贴板上,自己去微信里面粘贴搜索:),懒人会进行一系列复杂操作么,不看好 首先,百度了一下,看 ...

  7. BFC原理

    一.BFC是什么? 在解释 BFC 是什么之前,需要先介绍 Box.Formatting Context的概念. Box: CSS布局的基本单位 Box 是 CSS 布局的对象和基本单位, 直观点来说 ...

  8. Struts2中Action配置的三种方式

    <!-- 方案一:一个action对应一个方法; --> <action name="add" class="com.gxxy.struts.kp03_ ...

  9. MyFirstServlet学习笔记

    MyFirstServlet学习笔记 项目文件的结构目录如下,ser包,下设Serv.java是一个servlet文件,Note只是做的笔记,webroot下有login.jsp,WEB-INF下有w ...

  10. osprofiler在openstack Cinder里的使用

    最近在做OpenStack Cinder driver的性能调试, 之前一直是通过在driver里面加入decorator,完成driver各个接口的执行时间的统计. 其实在openstack,已经在 ...