问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Android应用进程间数据共享的几种方式——IPC

创作时间:
作者:
@小白创作中心

Android应用进程间数据共享的几种方式——IPC

引用
CSDN
1.
https://blog.csdn.net/github_27263697/article/details/145104560

Android应用进程间数据共享(IPC)是Android开发中的重要技术,本文系统地介绍了Bundle、文件共享、Messenger、AIDL、ContentProvider、Socket和Binder连接池等多种IPC方式,并对每种方式的实现原理、使用场景和优缺点进行了详细的说明。

一、Bundle

四大组件中的三大组件(Activity、Service、Receiver)都是支持在Intent中传递Bundle数据的,由于Bundle实现了Parcelable接口,所以它可以方便地在不同的进程间传输,这是一种最简单的进程间通信方式。

二、文件共享

文件共享方式适合在对数据同步要求不高的进程之间进行通信,并且要妥善处理并发读/写的问题。

当然,SharedPreferences是个特例,众所周知,SharedPreferences是Android中提供的轻量级存储方案,它通过键值对的方式来存储数据,在底层实现上它采用XML文件来存储键值对,每个应用的SharedPreferences文件都可以在当前包所在的data目录下查看到。一般来说,它的目录位于/data/data/package name/shared_prefs目录下,其中package name表示的是当前应用的包名。

从本质上来说,SharedPreferences也属于文件的一种,但是由于系统对它的读/写有一定的缓存策略,即在内存中会有一份SharedPreferences文件的缓存,因此在多进程模式下,系统对它的读/写就变得不可靠,当面对高并发的读/写访问, Sharedpreferences有很大几率会丢失数据,

因此,不建议在进程间通信中使用SharedPreferences。

三、Messenger信使

Messenger可以翻译为信使,顾名思义,通过它可以在不同进程中传递Message对象,在Message中放入我们需要传递的数据,就可以轻松地实现数据的进程间传递了。

Messenger是一种轻量级的IPC方案,它的底层实现是AIDL,从构造方法的实现上我们可以明显看出AIDL的痕迹,不管是IMessenger还是Stub.asInterface,这种使用方法都表明它的底层是AIDL。

实现一个Messenger有如下几个步骤,分为服务端和客户端:

  1. 服务端进程

首先,我们需要在服务端创建一个Service来处理客户端的连接请求,同时创建一个Handler并通过它来创建一个Messenger对象,然后在Service的onBind中返回这个Messenger对象底层的Binder即可。

  1. 客户端进程

客户端进程中,首先要绑定服务端的Service,绑定成功后用服务端返回的IBinder对象创建一个Messenger,通过这个Messenger就可以向服务端发送消息了,发消息类型为Message对象。如果需要服务端能够回应客户端,就和服务端一样,我们还需要创建一个Handler并创建一个新的Messenger,并把这个Messenger对象通过Message的replyTo参数传递给服务端,服务端通过这个replyTo参数就可以回应客户端。

四、AIDL

Messenger是以串行的方式处理客户端发来的消息,如果大量的消息同时发送到服务端,服务端仍然只能一个个处理,如果有大量的并发请求,那么用Messenger就不太合适了。同时,Messenger的作用主要是为了传递消息,很多时候我们可能需要跨进程调用服务端的方法,这种情形用Messenger就无法做到了,但是我们可以使用AIDL来实现跨进程的方法调用。

AIDL也是Messenger的底层实现,因此Messenger本质上也是AIDL,只不过系统为我们做了封装从而方便上层的调用而已。

  1. 服务端服务端首先要创建一个Service用来监听客户端的连接请求,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明,最后在Service中实现这个AIDL接口即可。

  2. 客户端客户端所要做事情就稍微简单一些,首先需要绑定服务端的Service,绑定成功后,将服务端返回的Binder对象转成AIDL接口所属的类型,接着就可以调用AIDL中的方法了。

在AIDL文件中,并不是所有的数据类型都是可以使用的,AIDL文件支持数据类型有:

  • 基本数据类型(int、long、char、boolean、double等);
  • String和CharSequence;
  • List:只支持ArrayList,里面每个元素都必须能够被AIDL支持;
  • Map:只支持HashMap,里面的每个元素都必须被AIDL支持,包括key和value;
  • Parcelable:所有实现了Parcelable接口的对象;
  • AIDL:所有的AIDL接口本身也可以在AIDL文件中使用。

以上6种数据类型就是AIDL所支持的所有类型,其中自定义的Parcelable对象和AIDL对象必须要显式import进来,不管它们是否和当前的AIDL文件位于同一个包内。

另外一个需要注意的地方是,如果AIDL文件中用到了自定义的Parcelable对象,那么必须新建一个和它同名的AIDL文件,并在其中声明它为Parcelable类型。

为了方便AIDL的开发,建议把所有和AIDL相关的类和文件全部放入同一个包中,这样做的好处是,当客户端是另外一个应用时,我们可以直接把整个包复制到客户端工程中,对于本例来说,就是要把com.ryg.chapter_2.aidl这个包和包中的文件原封不动地复制到客户端中。如果AIDL相关的文件位于不同的包中时,那么就需要把这些包一一复制到客户端工程中,这样操作起来比较麻烦而且也容易出错。需要注意的是,AIDL的包结构在服务端和客户端要保持一致,否则运行会出错,这是因为客户端需要反序列化服务端中和AIDL接口相关的所有类,如果类的完整路径不一样的话,就无法成功反序列化,程序也就无法正常运行。

五、ContentProvider

ContentProvider是Android中提供的专门用于不同应用间进行数据共享的方式,从这一点来看,它天生就适合进程间通信。和Messenger一样,ContentProvider的底层实现同样也是Binder,由此可见,Binder在Android系统中是何等的重要。虽然ContentProvider的底层实现是Binder,但是它的使用过程要比AIDL简单许多,这是因为系统已经为我们做了封装,使得我们无须关心底层细节即可轻松实现IPC。

六、Socket

Socket也称为“套接字”,是网络通信中的概念,它分为流式套接字和用户数据报套接字两种,分别对应于网络的传输控制层中的TCP和UDP协议。

TCP协议是面向连接的协议,提供稳定的双向通信功能,TCP连接的建立需要经过“三次握手”才能完成,为了提供稳定的数据传输功能,其本身提供了超时重传机制,因此具有很高的稳定性;

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

七、Binder连接池

AIDL是一种最常用的进程间通信方式,是日常开发中涉及进程间通信时的首选。

随着AIDL数量的增加,我们不能无限制地增加Service,Service是四大组件之一,本身就是一种系统资源。而且太多的Service会使得我们的应用看起来很重量级,因为正在运行的Service可以在应用详情页看到,当我们的应用详情显示有10个服务正在运行时,这看起来并不是什么好事。针对上述问题,我们需要减少Service的数量,将所有的AIDL放在同一个Service中去管理。

Binder连接池的主要作用就是将每个业务模块的Binder请求统一转发到远程Service中去执行,从而避免了重复创建Service的过程,它的工作原理如图2-10所示:

BinderPool能够极大地提高AIDL的开发效率,并且可以避免大量的Service创建,因此,建议在AIDL开发工作中引入BinderPool机制.

八、总结

本文详细介绍了Android应用进程间数据共享的多种方式,包括Bundle、文件共享、Messenger、AIDL、ContentProvider、Socket和Binder连接池等。每种方式都有其适用场景和优缺点,开发者可以根据具体需求选择合适的方式进行进程间通信。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号