Android学习笔记:Android进程间的几种通信方式

进程与线程

一般来说,Android系统中为一个应用程序开启一个进程进行执行,在这个应用程序中的所有组件,通过单独的线程进行执行,而其中所有的线程,共享该应用程序进程的所有资源。当一个应用程序启动的时候,Android系统启动一个新的Linux应用程序的进程和一个执行线程。在默认情况下,一个应用程序运行中的所有组件运行在相同的进程和线程中,这个线程一般称为主线程。如果一个应用程序的组件开始的时候,已经存在一个进程,那么应用程序会在与它相同的执行线程中开始这个组件。

进程

默认情况下,同一应用程序下的所有组件运行在同一进程中。然而,如果需要控制哪个进程属于哪个组件,可以在AndroidManifest.xml文件中进行配置。一般来说,组件元素:均支持属性android:process,可以通过设置这个属性让不同的组件单独运行在自己的进程中,也可以使用这个属性使不同的应用程序组件运行在相同的进程中,并共享相同的Linux用户ID和赋予同样的证书。

Android在内存较低的情况下,会关闭一些优先级较低的进程以增大内存运行更重要的进程,而在这个进程中的所有线程,也会被同时销毁。在内存足够的情况下,Android系统会尽可能保持应用程序进程,以达到下次的快速启动,但最终需要移除旧的进程,回收内存用于新的或更重要的进程。通过进程的优先级来判断是否被回收,一般会回收优先级较低的进程,以给优先级高的进程腾出资源。下面是五类Android进程,他们的优先级顺序排列:

  1. Foreground process:前台进程。
  2. Visible prcess:可见进程。
  3. Service process:服务进程。
  4. Background process:后台进程。
  5. Empty process:空进程。

Tips:一个进程的优先级是可以变化的。

线程

当应用程序启动时,系统会创建一个执行线程在这个应用程序的进程中,一般被称为“主线程”。这个线程是非常重要的,因为它负责把事件分发给响应的用户组件,包括绘制事件等,因此主线程又被称为UI线程。系统并不会为每个组件创建一个单独的线程,而是在UI线程中,完成这些组件的初始化的,因此系统回调方法是运行在UI线程中,如click事件。

进程间通信 Inter-process communication,IPC

Bundle/Intent传递数据

1、Activity、Service、Receiver都支持在Intent中传递Bundle数据,而Bundle实现了Parcelable接口,可以在不同的进程间进行传输。
2、在一个进程中启动了另一个进程的Activity、Service和Receiver ,可以在Bundle中附加要传递的数据通过Intent发送出去。

使用文件共享

Android系统是基于Linux的,其并发读取文件没有限制,并且允许同时对文件进行读写操作

使用Messenger

Messenger是一种轻量级的进程间通信方案,其底层是基于AIDL实现的。服务端(被动方)提供一个Service来处理客户端(主动方)连接,维护一个Handler来创建Messenger,在onBind时返回Messenger的binder。

Messenger处理数据依靠的是Handler,一次只能处理一个请求,所以是串行的,服务器端不存在并发执行的情况。

使用AIDL

Messenger是通过串行的方式来处理请求的,所以Messenger方式不适用于大量并发请求的情形,而且 Messenger 只适合传递消息。AIDL 可以解决并发和跨进程调用方法的问题。

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

客户端:绑定服务端的 Service ,绑定成功后,将服务端返回的 Binder 对象转成 AIDL 接口所属的类型,然后就可以调用 AIDL 中的方法了。客户端调用远程服务的方法,被调用的方法运行在服务端的 Binder 线程池中,同时客户端的线程会被挂起,如果服务端方法执行比较耗时,就会导致客户端线程长时间阻塞,导致 ANR。客户端的 onServiceConnected 和 onServiceDisconnected 方法都在 UI 线程中。

使用ContentProvider

ContentProvider是Android四大组件之一,主要用于不同应用之间的数据共享,和 Messenger 底层实现同样是 Binder 和 AIDL,系统做了封装,使用简单。使用方法:继承 ContentProvider 类并实现onCreate、getType、query、insert、delete 和 update 这6 个抽象方法,这六个方法均运行在 ContentProvider 进程中,除 onCreate 运行在主线程里,其他五个方法均由外界回调运行在 Binder 线程池中。

使用Socket

Socket 起源于 Unix,而 Unix 的基本哲学之一就是“一切皆文件”,都可以通过“打开 open – 读写 write/read – 关闭 close ”模式来操作。Socket 就是该模式的一个实现,网络的 Socket 数据传输是一种特殊的 I/O,Socket 也是一种文件描述符。Socket 也具有一个类似于打开文件的函数调用:Socket(),该函数返回一个整型的Socket 描述符,随后的连接建立、数据传输等操作都是通过该 Socket 实现的。

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

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

 

名称 优点 缺点 适用场景

使用Bundle/Intent

简单易用 只能传输Bundle支持的数据类型 四大组件间的进程间通信
文件共享 简单易用 不适用高并发场景,并且无法做到进程间即时通信 适用于无并发的情况下,交换简单的数据,对实时性要求不高的场景
使用Messenger 功能一般,支持一对多串行通信,支持实时通信 不能很好地处理高并发的情形,不支持RPC,由于数据通过Message传输,因此只能传输Bundle支持的数据类型 低并发的一对多实时通信,无RPC需求,或者无需要返回结果的RPC需求

使用AIDL

功能强大,支持一对多实时并发通信 使用稍复杂,需要处理好线程间的关系 一对多通信且有RPC需求
使用ContentProvider 支持一对多的实时并发通信,在数据源共享方面功能强大,可通过Call方法扩展其它操作 可以理解为受约束的AIDL,主要提供对数据源的CRUD操作 一对多的进程间数据共享
使用Socket 功能强大,可通过网络传输字节流,支持一对多实时并发通信 实现细节步骤稍繁琐,不支持直接的RPC 网络间的数据交换


 

 

你可能感兴趣的:(Android,android,java)