概要

  • 多进程概念及多进程常见注意事项
  • 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机制(三)在Android Studio中使用AIDL实现跨进程方法调用

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

  2. Android IPC机制全解析<一>

    概要 多进程概念及多进程常见注意事项 IPC基础:Android序列化和Binder 跨进程常见的几种通信方式:Bundle通过Intent传递数据,文件共享,ContentProvider,基于Bi ...

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

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

  4. Android IPC机制—Binder的工作机制

    进程和线程的关系 IPC机制即为跨进程通信,是inter-Process Communication的缩写.是指两个进程之间进行通信.在说进程通信之前,我们的弄明白什么是线程,什么是进程.进程和线程是 ...

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

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

  6. Android IPC机制(五)用Socket实现跨进程聊天程序

    1.Socket简介 Socket也称作“套接字“,是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用以实现进程在网络中通信.它分为流式套接字和数据包套接 ...

  7. Android IPC机制之AIDL

    什么是AIDL AIDL:Android Interface Definition Language,即Android接口定义语言. Android系统中的进程之间不能共享内存,因此,需要提供一些机制 ...

  8. Android IPC机制(二)用Messenger进行进程间通信

    Messenger可以在不同进程中传递Message对象,我们在Message中加入我们想要传的数据就可以在进程间的进行数据传递了.Messenger是一种轻量级的IPC方案并对AIDL 进行了封装, ...

  9. Android IPC机制之ContentProvider

    ContentProvider:即内容提供者,用来管理数据,并对外暴露一个uri,外部可以通过uri和数据建立联系并获取或操作数据: 服务端:1.首先创建一个数据库类,并创建一个表:2.创建一个Con ...

随机推荐

  1. Form表单发送到服务器时的编码方式

    ---恢复内容开始--- 表单中的表单中enctype是设置表单的MIME编码. 所谓MIME编码,是指当服务器传送数据给客户端时,必须指定这个文件是什么类型,才能方便客户端调用相应的应用软件来打开该 ...

  2. yml多环境配置

    配置独立各自的环境 注:如果需要修改环境测试,只需要修改spring: profiles: active: “环境名” spring: profiles: active: prd --- #开发环境配 ...

  3. 小程序for循环绑定每组数据的id,并通过id获取里面某个数组的值的方法

    WXML: <block wx:for="{{nums}}" wx:for-index='key' wx:for-item='item'> <view class ...

  4. 如何调用别人提供的webservice接口

    当我们拿到一个接口的时候,先别急着去调用它,我们得先测试这个接口是否正确,是否能调用成功,以及返回的数据是否是我们需要的类型等等.这时候我们需要一个工具,比如SoapUI.(最好用绿色免安装版的.)然 ...

  5. CSS3-3

    关于背景 一. 渐变&径向渐变(background-image: -webkit-linear-gradient() && background-image: -webkit ...

  6. SSM--spring框架

    他是SpringFramework创始人,interface21 CEO Spring 的作者:Rod Johnson 一  :Spring的核心IOC和AOP(本处详解IOC) IOC:控制反转:( ...

  7. Unity实现用户条款弹窗及登录

    首先来看效果图... 1.先编辑页面 1)新建登录按钮,更名为Login 2)新建toggle,新建方式如下图 调整toggle的大小和位置到适当的范围. 3)新建同意用户条款按钮,步骤为新建UI-& ...

  8. Android Touch事件相关源码【Android SourceCode 2.3.6】

    2018-05-31 17:23:46 Note: 这里的源码来自Android 2.3.6,这个版本的代码比较简单,适合理解Touch事件的传递原理.后续版本源码复杂了很多,但是原理都是类似的. 2 ...

  9. CEPH集群操作入门--配置

      参考文档:CEPH官网集群操作文档   概述 Ceph存储集群是所有Ceph部署的基础. 基于RADOS,Ceph存储集群由两种类型的守护进程组成:Ceph OSD守护进程(OSD)将数据作为对象 ...

  10. Dictionary集合运用

    Dictionary基础定义: 从一组键(key)到一组值(value)的映射,每一个添加项都是由一个值及其相关联的键组成: 任何键都必须是唯一的: 键不能为空引用的null(VB中的Nothing) ...