AIDL是啥
在Android中谷歌规定:两个进程之间不能直接通信,当我们需要在一个进程中想要得知另一个进程的数据,这个时候该怎么办呢?
谷歌定义了4种跨进程的通信方式,分别对应着android的四大组件每个组件一种方法,进程A将数据提交给系统,系统再接着将数据提交给进程B,这种间接的共享数据的方法在 Service这个组件里面 就叫 AIDL。
AIDL是Android interface definition Language (Android接口定义语言)的简写,是一种进程通信(IPC)的机制,我们可以利用它定义客户端与服务使用进程间通信进行相互通信时都认可的编程接口。
如何使用AIDL
进程需要将其对象分解成操作系统能够识别的原语,并将对象编组成跨越边界的对象。
编写执行这一编组操作的代码是一项繁琐的工作,因此 Android 会使用 AIDL 来处理。
通过这种机制,我们只需要写好 aidl 接口文件,编译时系统会帮我们生成 Binder 接口。
简而言之,我们需要打包我们实体类的同时写一个aidl接口文件。
官方文档定义:
使用AIDL时会对内存进行读取,所以经常使用会造成程序变慢,所以不要过多使用
当只使用IPC,不用多线程并使用多个应用程序时,只使用binder就行了
而只有用IPC,不用多线程时,只使用message就好了
AIDL有必要用于使用IPC,处理多线程并且在多个应用程序间共享程序
AIDL支持的数据
- JAVA的默认基本数据类型(String,int。。。 short除外)
- List和Map
- 其它的AIDL接口
- 实现Parcelable的实体类
使用AIDL步骤
- 创建aidl
①创建实体类并实现Parcelable接口
②新建aidl文件,在其下面创建aidl的映射文件和接口文件
③通过build后生成binder的java文件 - 服务端
①创建service,在其中创建上面生成binder的实例,实现接口定义的方法
②在onBind()中返回 - 客户端
①实现ServiceConnection接口,在其中拿到AIDL类
②用bindService()绑定service
③使用aidl中的操作
AIDL实例:
(先演示一个小的)
服务端做出了一个A+B的功能,而客户端没有这个功能的时候他要去服务端调用这个功能。
首先在创建IMyaidl文件
// IMyaidl.aidl
package com.rikka.myaidl2;
// Declare any non-default types here with import statements
interface IMyaidl {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
int add(in int num1,in int num2);
}
因为只是个a+b的功能,所以没有实体类呀parcelable的说法
然后点个锤子make project产生myaidl
此时去服务端完成这个a+b的功能,新建myservice类
在其中实现onbind()和Stub()
public class MyService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mIbinder;
}
private IBinder mIbinder = new IMyaidl.Stub() {
@Override
public int add(int num1, int num2) throws RemoteException {
return num1+num2;
}
};
}
这里的 new IMyaidl.Stub()函数的返回类型是Ibinder,它先实现IMyaidl里面的接口功能,然后向上转型为Ibinder类型,同时通过onBind()传出。这样做是为了当客户端的activity要去用这个服务端的这个功能时,客户端先要绑定这个service,这时候客户端就能得到这个IBinder了。
接下来客户端要绑定服务,并且通过传入两个值a和b给服务端,让服务端完成a+b
首先要客户端实现接口 ServiceConnection ,在连接服务的时候得到AIDL类
IMyaidl im;
ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
im = IMyaidl.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
im = null;
}
};
这里的 asInterface(service) 就是将绑定之后(现在还没有绑定服务,等下通过bindservice()绑定服务得到了ibinder)将Ibinder转化为aidl类。im就是这个aidl类。如下:
Intent intent = new Intent(getApplicationContext(),MyService.class);
bindService(intent,mConnection,BIND_AUTO_CREATE);
最后通过button来实现a+b
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
x1= Integer.parseInt(num1.getText().toString());
x2= Integer.parseInt(num2.getText().toString());
try {
ans = im.add(x1,x2);
} catch (RemoteException e) {
e.printStackTrace();
}
res.setText(ans + "");
}
});
这就完成了客户端申请到服务端的功能。
现在还在看里面的一些基于stub、asinterface的代码,下几篇再去完成一个关于parcelable实体类的IPC例子。