【Android跨进程】IPC总结

前言

IPC是Inter-Process Communication的缩写,含义就是进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程。两个进程可以是两个独立的app也可以是一个app的两个进程。

跨进程常见的几种通信方式:Bundle通过Intent传递数据,文件共享,ContentProvider,基于Binder的AIDL和Messenger以及Socket。本文主要是做个总结,详细展开会在后续独立成文。

Android底层是基于Linux,而Linux基于安全考虑,是不允许两个进程间直接操作对方的数据,这就是进程隔离

在Linux系统中,虚拟内存机制为每个进程分配了线性连续的内存空间,操作系统将这种虚拟内存空间映射到物理内存空间,每个进程有自己的虚拟内存空间,进而不能操作其他进程的内存空间,每个进程只能操作自己的虚拟内存空间,只有操作系统才有权限操作物理内存空间.进程隔离保证了每个进程的内存安全,但是在大多数情形下,不同进程间的数据通讯是不可避免的,因此操作系统必须提供跨进程通信机制。

一、Intent & Bundle方式

  1. Activity,Service,Receiver 都支持在 Intent 中传递 Bundle 数据,而 Bundle 实现了 Parcelable 接口,可以在不同的进程间进行传输。(四大组件中三大组件)
  2. 在一个进程中启动了另一个进程的 Activity,Service 和 Receiver ,可以在 Bundle 中附加要传递的数据通过 Intent 发送出去。
private void startWithIntent() {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.owen.stud", "com.owen.stud.intentIpcActivity"));
        //制定要打开的程序的包名和地址(activity名)
        Bundle bundle = new Bundle();//通过budle传递数据,可以携带序列化数据
        bundle.putInt("intextra", 0);
        bundle.putString("stringextra", "");
        intent.putExtras(bundle);
        try {
            startActivity(intent);
        }catch (Exception e){
            ToastUtils.showMessage("没有找到对应文件");
        }
    }

二、使用文件共享

  1. Windows 上,一个文件如果被加了排斥锁会导致其他线程无法对其进行访问,包括读和写;而 Android 系统基于 Linux ,使得其并发读取文件没有限制地进行,甚至允许两个线程同时对一个文件进行读写操作,尽管这样可能会出问题。
  2. 可以在一个进程中序列化一个对象到文件系统中,在另一个进程中反序列化恢复这个对象(注意:并不是同一个对象,只是内容相同。)。
  3. SharedPreferences 是个特例,系统对它的读 / 写有一定的缓存策略,即内存中会有一份 ShardPreferences 文件的缓存,系统对他的读 / 写就变得不可靠,当面对高并发的读写访问,SharedPreferences 有很多大的几率丢失数据,不那么可靠。因此,IPC 不建议采用 SharedPreferences。

 

三、使用 Messenger

Messenger 是一种轻量级的 IPC 方案,它的底层实现是 AIDL ,可以在不同进程中传递 Message 对象,它一次只处理一个请求,在服务端不需要考虑线程同步的问题,服务端不存在并发执行的情形。

Messenger是基于AIDL实现的,服务端(被动方)提供一个Service来处理客户端(主动方)连接,维护一个Handler来创建Messenger,在onBind时返回Messenger的binder。

双方用Messenger来发送数据,用Handler来处理数据。Messenger处理数据依靠Handler,所以是串行的,也就是说,Handler接到多个message时,就要排队依次处理。

 

四、使用 AIDL

Messenger 是以串行的方式处理客户端发来的消息,如果大量消息同时发送到服务端,服务端只能一个一个处理,所以大量并发请求就不适合用 Messenger ,而且 Messenger 只适合传递消息,不能跨进程调用服务端的方法。AIDL 可以解决并发和跨进程调用方法的问题,要知道 Messenger 本质上也是 AIDL ,只不过系统做了封装方便上层的调用而已。

 

五、使用 ContentProvider

用于不同应用间数据共享,和 Messenger 底层实现同样是 Binder 和 AIDL,系统做了封装,使用简单。 系统预置了许多 ContentProvider ,如通讯录、日程表,需要跨进程访问。 使用方法:继承 ContentProvider 类实现 6 个抽象方法,这六个方法均运行在 ContentProvider 进程中,除 onCreate 运行在主线程里,其他五个方法均由外界回调运行在 Binder 线程池中。

ContentProvider 的底层数据,可以是 SQLite 数据库,可以是文件,也可以是内存中的数据。

 

六、使用 Socket

常用的 Socket 类型有两种:流式 Socket(SOCK_STREAM)和数据报式 Socket(SOCK_DGRAM)。流式是一种面向连接的 Socket,针对于面向连接的 TCP 服务应用;数据报式 Socket 是一种无连接的 Socket ,对应于无连接的 UDP 服务应用。

Socket 本身可以传输任意字节流。

谈到Socket,就必须要说一说 TCP/IP 五层网络模型:

  • 应用层:规定应用程序的数据格式,主要的协议 HTTP,FTP,WebSocket,POP3 等;
  • 传输层:建立“端口到端口” 的通信,主要的协议:TCP,UDP;
  • 网络层:建立”主机到主机”的通信,主要的协议:IP,ARP ,IP 协议的主要作用:一个是为每一台计算机分配 IP 地址,另一个是确定哪些地址在同一子网;
  • 数据链路层:确定电信号的分组方式,主要的协议:以太网协议;
  • 物理层:负责电信号的传输。

Socket 是连接应用层与传输层之间接口(API)。

只实现 TCP Socket 。

 

 

 参考:https://github.com/LRH1993/android_interview/blob/master/android/basis/ipc.md#%E4%BA%8C%E4%BD%BF%E7%94%A8%E6%96%87%E4%BB%B6%E5%85%B1%E4%BA%AB

https://blog.csdn.net/hzw2017/article/details/81275438

 

posted @ 2019-05-26 23:51  Ivo-oo  阅读(348)  评论(0编辑  收藏  举报