欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android IPC(inner process communication)进程间通信解析

程序员文章站 2022-03-27 21:33:57
Android IPC(inner process communication)进程间通信解析,我们android在面试的时候,面试官会问到我们IPC,这个被问到的概率非常大,...

Android IPC(inner process communication)进程间通信解析,我们android在面试的时候,面试官会问到我们IPC,这个被问到的概率非常大,当然我每一次都会被问到,所以我总结了一下IPC,通过看一些大牛的书籍。

一。android IPC简介

IPC是Inter-process Communication的缩写。含义就是进程间的通讯或者夸进程通讯,是指两个进程间进行数据交换的过程,那么什么是进程,什么是线程,进程和线程是两个截然不同的概念,在操作系统中,线程是CPU调度的最小单位,同时线程是一种有限的系统资源,而进程指的一个执行单位,在PC和移动设备上指的是一个程序或者一个应用,一个进程可以包含多个线程,因此进程和线程是包含和被包含的关系,最简单情况下,一个进程可以只有一个线程,即主线程,在android里面也叫UI线程,在UI线程里才能操作界面元素。

那么在android中,有特色的进程间的通讯方式就是Binder了,通过Binder可以轻松实现进程间的通信,除了Binder,android还支持Scoket,通过Scoket也可以实现任意两个终端之间的通信,当然一个设备上的两个进程之间通过Scoket通信自然也是可以的;

说到IPC的使用场景就必须提到多进程,只有面对多进程这种场景下,才需要考虑进程间的通信,所有运行在不同进程中的四大组件,只要他们之间需要通过内存来共享数据,都会共享失败,这也是多进程所带来的主要影响,正常情况下,四大组件之间不可能不通过一些中间层来共享数据,那么通过简单地指定进程名来开启进程都会无法正确运行,一般来说,使用多进程会造成如下几方面的问题:

1.静态成员和单例模式完全无效

2,线程同步机制完全失效

3.SharedPerences的可靠性下降

4,Application会多次创建

为了解决这个问题,系统提供了很多跨进程通信方法,虽然说不能直接地共享内存,但是通过跨进程通信我们还是可以实现数据交互,实现跨进程通信的方式有很多,

二。IPC的方式

1.Bundle

一个进程启动另一个进程,Bundle将信息通过Intent发送出去。

条件:

传输数据必须能够被序列化,比如基本类型, Parcelable接口对象,

Bundle不支持的类型无法进程间传递数据,

还有一个特殊使用场景:

A进程正在进行计算,计算完成后要启动B进程的一个组件并把计算结果传递给B进程,

可是遗憾的是计算结果不止持Bundle,无法通过Intent传递,

解决办法:

通过Intent启动进程B的一个service组件(IntentService),让service在后台进行计算,

计算完毕之后,启动B进程真正要启动的目标组件,

这种方法的核心思想:

将原本需要在A进程的计算任务转移到B进程的后台Service中去执行,这样就成功的避免了进程间通信问题,

2.使用文件共享

1.简介

共享文件也是一种很不错的进程间通讯方式。两个进程通过读写同一个文件来交换数据,

在Windows上,一个文件如果被加上了排斥锁导致其他线程无法对其进行访问,包括读写,

android基于Linux,使得并发读写文件可以没有限制的进行

2,共享文件格式要求

文件共享对文件格式是没有具体要求的,文本文件,xml文件,

3.为什么不建议在进程间通讯使用SharedPreferences?

Sharedpreferences是一个轻量级存储方案,通过键值对的方式存储数据,在底层采用xml文件来存储键值对,由于系统对它的读写有一定的缓存策略,即内存中会有一份Shardpreferences文件的缓存,在多进程模式下,系统对它的读写就会变得不靠谱,当面对高并发的读写访问,Sharedpreferences

有很大的几率会丢失数据。

3。使用messager

Messager可以翻译为信使,他可以在不同的进程中传递Message对象,在message中放入我们需要传递的数据,就可以实现进程间传递了。

Messager是一种轻量级的IPC方案,它的底层是AIDL,它对AIDL进行了封装,使得我们可以更简便的进行进程间通讯,它一次处理一个请求,不需要考虑进程同步问题。

实现Messager分为服务端和客户端

1.服务端进程:

在服务端创建一个service来处理客户端的连接请求,同时创建一个Handler,并通过它来创建一个Messager对象,然后在Service的onBind中返回这个Messager对象底层的Binder

2.客户端

绑定服务端的service,绑定成功后服务端会返回Ibinder对象创建一个Messager,通过Messager向服务端发送消息,发送消息类型为Message对象,如果需要服务端能够回应客户端,就和服务端一样,

我们还需要创建一个Handler并创建一个新的Messager,并把这个Messager对象通过Message的replyTo参数传递给服务端,服务端通过replyTo参数就可以回应客户端。

Messager中进行数据传递必须将数据放入Message中,而Messager和message都实现了Parcelable

接口,因此可以跨进程传输,

4.使用AIDL

Messager是以串行的方式处理客户端发来的消息,如果大量的消息同时发送到服务端,服务端

仍然一个一个的处理,如果有大量的并发请求,那么用messager就不合适了,

messager主要是为了传递消息,无法做到跨进程调用服务端的方法,但是我们可以使用 AIDL

实现跨进程的方法调用,

AIDL进行进程间通信的流程,分为服务端和客户端

1.服务端

创建一个service用来监听客户端的连接请求,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明,最后在这个service中实现这个AIDL接口

2.客户端

需要绑定服务端的service,成功后将服务端返回的Binder对象转换成AIDL接口所属的类型,接着就可以调用AIDL的方法(这只是一个感性过程,实现过程远不止这么简单)

3.接口的创建

我们创建一个后缀为AIDL的文件,在这里声明了一个接口和两个接口的方法

4.AIDL所支持的类型,(AIDL并不是所有的类型都是可以使用的)

1)基本数据类型

2 )String 和 CharSequence

3 )List:只支持arrayList

4 )Map: 只支持HashMap

5)Parcelable:所有的AIDL接口本身也可以在AIDL文件中使用

6)AIDL:所有的AIDL接口本身也可以在AIDL文件中使用

5.使用contentProvider

ContentProvider是android中专门用于不同应用间数据共享的方式,所以天生适合进程间通信。

ContentProvider底层也是Binder,使用过程比AIDL简单,这是因为系统给他做了封装,使得我们无需

关心底层细节就可以轻松实现IPC.

系统预置了许多ContentProvider,比如通讯录信息,日程表信息等,要跨进程访问这些信息,只需要通过ContentProvider的query.update,insert,delete方法即可。

如何实现进程间通讯这一幕?

创建一个自定义的ContentProvider,只需要继承ContentProvider类,并实现6个抽象方法,

1)onCreate():代表ContentProvier的创建,一般来说我们需要做一些初始化

2)getType:用来返回一个URL请求所对应的媒体类型,如果我们的应用不关注这个选项,我们直接

在这个方法中直接返回null

3)query.update,insert,delete方法:实现对数据表的增删改查功能

根据binder的工作原理,这6个方法均运行在ContentProvider的进程中,除了onCreate有系统

回调运行在主线程中,其他五个方法均由外界回调并运行在Binder线程池中,

6.使用Socket

Socket也称为“套接字”,是网路通信中的概念,它分为流式套接字和用户数据报套接字两种,分别对应于网络的传输控制层中的TCP和UDP协议,TCP协议是面向连接的协议,提供稳定的双向通讯功能,TCP连接的建立需要经过三次握手才能完成,为了提供稳定的数据传输功能,其本身提供了超时

重传机制,因此具有很高的稳定性,而UDP是无连接的,提供不稳定的单向通讯功能,当然UDP也可以实现双向通讯功能,在性能上UDP具有更好的效率,缺点不能保证数据一定能够正确传输,尤其在网络堵塞的情况下,

三。选择适用的IPC方式

名称 优点 缺点 适用场景

Bundle 简单易用 只能传输Bundle支持 四大组件间的

的数据类型 进程通讯

文件共享 简单易用 不适用高并发场景,并且 无并发访问情形,交换简的

无法做到进程间的即时通讯 数据实时性不高的场景

AIDL 功能强大,支持 使用稍复杂,需要处理好线程 一对多通信且有RPC需求

一对多并发通信, 同步

支持实时通信。

Messager 功能一般,支持一对多 不能很好的处理高并发 低并发的一对多即时通信

串行通信,支持实时通信 情形,不支持RPC,数据 无RPC需求,或者无需

通过message进行传输 要返回结果的RPC需求

因此只能传输Bundle支持

数据类型。

ContentProvider 在数据源访问方面功能强大 可以理解为受约束的AIDL, 一堆多的进程间的

支持一对多并发数据共享,可 主要提供数据源的CRUD 数据共享

通过call方法扩展其他操作, 操作。

Socket 功能强大,可以通过网络传输 实现细节稍微有点繁琐, 网络数据交换

字节流,支持一对多并发 不支持直接的RPC

实时通讯