Android进程间通信(全解)

进程间通信简称IPC(Inter-Process Communication).Android 基于Linux,,而 Linux 出于安全考虑,不同进程间不能之间操作对方的数据,这叫做“进程隔离”。这样做的目的是为了保证每个进程的安全。

IPC方式

名称优点缺点适用场景
Bundle简单易用只能传输 Bundle 支持的数据类型四大组件间的进程间通信
文件共享简单易用不适合高并发场景,并且无法做到进程间即时通信无并发访问情形,交换简单的数据实时性不高的场景
AIDL功能强大,支持一对多并发通信,支持实时通信使用稍复杂,需要处理好线程同步一对多通信且有 RPC 需求
Messenger功能一般,支持一对多串行通信,支持实时通信不能很处理高并发清醒,不支持 RPC,数据通过 Message 进行传输,因此只能传输 Bundle 支持的数据类型低并发的一对多即时通信,无RPC需求,或者无需返回结果的RPC需求
ContentProvider在数据源访问方面功能强大,支持一对多并发数据共享,可通过 Call 方法扩展其他操作可以理解为受约束的 AIDL,主要提供数据源的 CRUD 操作一对多的进程间数据共享
Socket可以通过网络传输字节流,支持一对多并发实时通信实现细节稍微有点烦琐,不支持直接的RPC网络数据交换

 Binder

提到Binder,我们就会想到,他是android底层主要的进程间通信的,Binder机制只是IPC的其中一种,Android的四大组件(Activity,service,Broadcast,ContentProvider)之间的通信也是采用了Binder进行的通信。

IPC通信不得不提到两个序列化的组件,他们基本上是跟Binder绑定使用的:

    Serialiazable,Parcelable

Serializable和Parcelable接口可以完成对象的序列化过程,当我们需要通过Intent和Binder传输数据的时候就需要对数据进行序列化处理。还有的时候我们需要将数据持久化保存到本地或者通过网络传输给其他终端,我们也需要Serializable完成对象的持久化。

Serialiazable:Java提供的序列化接口(标记接口)
Parcelable:android提供的序列化接口

  • Serializable 是Java中的序列化接口,使用起来简单;Parcelable是Android中的序列化方式,使用起来稍微复杂一些。
  • Serializable 在序列化操作的时候会产生大量的临时变量,从而导致GC的频繁调用(原因是使用了反射机制);Parcelable是以Ibinder作为信息载体的,在内存上的开销比较小,因此在内存之间进行数据传递的时候,Android推荐使用Parcelable
  • 将对象序列化到存储设备上或者序列化后通过网络传输,使用Parcelable 会稍显复杂,因此这两种情况建议使用Serializable

下面,正式进入主题,Binder:

我们查看androidBinder底层源码发现,Binder是集成了IBinder接口,而我们从各个不同的角度来看Binder的具体使用:

1, 从IPC角度,Binder是跨进程通信方式
2, 从FrameWork角度,Binder是ServiceManager连接各种Manager(如am,wm)等的桥梁
3, 从应用层角度,Binder是客户端与服务端通信的媒介

 

下面来分析一下这个图,这张图,就是Binder底层框架结构图,他们是什么意思呢?

首先,Binder在Client中设置一个引用,在Server中设置一个实体,Client通过Binder间接的引用Server中的实体,这就实现了进程间的通信了。当然,Android系统不可能只为两个进程考虑通信问题,如果存在多个server,多个Client,那么此时Android系统就推出了一个Service Manager这个中间类,在这里,Service Manager就像是一个中介一样,所有的Server都必须去ServiceManager那里去注册,然后生成一个索引,此时,Client通过ServiceManager去找到这个索引,从而找到相对应的Server,这就构成了android底层多进程之间通信,而并不影响多进程的独立安全性的框架设计结构

当然,看过源码,我们知道ServiceManager他其实也是一个进程,那既然这样,Server与ServiceManager 他们之间又是如何进行通信的呢?

SMgr和其它进程同样采用Binder通信,SMgr是Server端,有自己的Binder对象(实体),其它进程都是Client,需要通过这个Binder的引用来实现Binder的注册,查询和获取。SMgr提供的Binder比较特殊,它没有名字也不需要注册,当一个进程使用BINDER_SET_CONTEXT_MGR命令将自己注册成SMgr时Binder驱动会自动为它创建Binder实体(这就是那只预先造好的鸡)。其次这个Binder的引用在所有Client中都固定为0而无须通过其它手段获得。也就是说,一个Server若要向SMgr注册自己Binder就必需通过0这个引用号和SMgr的Binder通信。类比网络通信,0号引用就好比域名服务器的地址,你必须预先手工或动态配置好。要注意这里说的Client是相对SMgr而言的,一个应用程序可能是个提供服务的Server,但对SMgr来说它仍然是个Client。

而上面说完了,我们来看Binder Driver(Binder驱动)

和路由器一样,Binder驱动虽然默默无闻,却是通信的核心。尽管名叫‘驱动’,实际上和硬件设备没有任何关系,只是实现方式和设备驱动程序是一样的。它工作于内核态,驱动负责进程之间Binder通信的建立,Binder在进程之间的传递,Binder引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。

AIDL 通信

Android Interface Definition Language

使用示例:

  • 新建AIDL接口文件
// RemoteService.aidl
package com.example.mystudyapplication3;

interface IRemoteService {

    int getUserId();

}
  • 创建远程服务
public class RemoteService extends Service {

    private int mId = -1;

    private Binder binder = new IRemoteService.Stub() {

        @Override
        public int getUserId() throws RemoteException {
            return mId;
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        mId = 1256;
        return binder;
    }
}

声明远程服务
<service
    android:name=".RemoteService"
    android:process=":aidl" />
  • 绑定远程服务
public class MainActivity extends AppCompatActivity {

    public static final String TAG = "wzq";

    IRemoteService iRemoteService;
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iRemoteService = IRemoteService.Stub.asInterface(service);
            try {
                Log.d(TAG, String.valueOf(iRemoteService.getUserId()));
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            iRemoteService = null;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindService(new Intent(MainActivity.this, RemoteService.class), mConnection, Context.BIND_AUTO_CREATE);
    }
}

Messenger

Messenger可以在不同进程中传递 Message 对象,在Message中放入我们需要传递的数据,就可以轻松地实现数据的进程间传递了。Messenger 是一种轻量级的 IPC 方案,底层实现是 AIDL。

Socket通信

此通信我们单独在后面网络进程中再讲述。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值