文章已同步github博客:AIDL中的数据流向
1、AIDL文件
1.1、文件类型
文件后缀名为.aidl;
1.2、数据类型
1.2.1、默认支持类型
默认支持的类型不需要导包;
- Java八种基本类型:byte、short、int、long、float、double、boolean、char;
- String类型;
- CharSequence类型;
- List类型:List中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable,List可以使用泛型;
- Map类型:Map中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable,Map是不支持泛型的,使用时需要显示导包;
1.2.2、parcelable对象
如自定义实体类实现Parcelable接口,使用时需要显示导包,即使目标文件与当前正在编写的.aidl文件在同一个包下;
1.3、定向tag
- in:单向数据流,客户端到服务端;
- out:单向数据流,服务端到客户端;
- inout:双向数据流,客户端与服务端双向流通;
Java中的基本类型和String、CharSequence的定向tag默认且只能是in;
1.3.1、in
客户端数据流向服务端,即客户端的值(实体类)即时同步到服务端,服务端可以拿到客户端传递的实体类,此时在服务端对接收到的客户端传来的数据做修改,服务端发生变化,客户端不发生变化,因为单向流动,除非调用接口方法,返回服务端修改的数据,客户端才能拿到服务端修改后的数据;
1.3.2、out
服务端数据流向客户端,即客户端的数据信息不向服务端同步(传递对象,对象不为空,但是没有数据),但是服务端拿到传递的对象后修改数据,能及时同步到客户端;
1.3.3、inout
双向流向,即服务端能拿到客户端传递的数据,服务端修改后客户端能及时同步到数据;
1.4、两种aidl文件
- 一类是用来定义parcelable对象,以供其他AIDL文件使用AIDL中非默认支持的数据类型的;
- 一类是用来定义方法接口,以供系统使用来完成跨进程通信的;
2、AIDL的使用
2.1、定义.aidl文件
2.1.1、实体类定义
定义实体类,作为进程间交互的数据,实现Parcelable接口;
public class ImageData implements Parcelable {
private String mImageName;
private int mImageSize;
private byte[] mImageArray;
public ImageData() {
}
protected ImageData(Parcel in) {
readFromParcel(in);
}
public static final Creator<ImageData> CREATOR = new Creator<ImageData>() {
@Override
public ImageData createFromParcel(Parcel in) {
return new ImageData(in);
}
@Override
public ImageData[] newArray(int size) {
return new ImageData[size];
}
};
// 省略getter和setter方法
...
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mImageName);
dest.writeInt(mImageSize);
dest.writeByteArray(mImageArray);
}
public void readFromParcel(Parcel dest) {
this.mImageName = dest.readString();
this.mImageSize = dest.readInt();
this.mImageArray = dest.createByteArray();
}
// 省略toString方法
...
}
2.1.2、.aidl接口定义
定义.aidl接口,这里为了验证客户端与服务端的数据变化,定义了三个接口方法;
// 显示导包
interface ImageShareInterface {
List<ImageData> getImages();
// flag为in
ImageData showImageIn(in ImageData data);
// flag为out
ImageData showImageOut(out ImageData data);
// flag为inout
ImageData showImageInOut(inout ImageData data);
}
定义实体类的aidl文件;
// 该文件需要与ImageData实体类文件的包名相同
import com.xxx.ImageData;
parcelable ImageData;
此时完成之后,build工程,会生将.aidl文件接口生成对应的java文件,生成目录如下:
build/generated/aidl_source_output_dir/debug/compileDebugAidl/out/<package>/
2.2、server端实现
-
自定义Service继承Service类,实现onBind()方法;
@Override public IBinder onBind(Intent intent) { return imageShareMgr; }
-
声明2.1.2中生成的java接口文件中的Stub类,并实现定义的方法,最后将该对象在onBind()方法中返回,用于将该IBinder对象传递给客户端使用;
private final ImageShareInterface.Stub imageShareMgr = new ImageShareInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public List<ImageData> getImages() throws RemoteException { synchronized (this) { if (imageDatas != null) { return imageDatas; } } return new ArrayList<>(); } @Override public ImageData showImageIn(ImageData data) throws RemoteException { synchronized (this) { if (imageDatas == null) { imageDatas = new ArrayList<>(); } if (data == null) { data = new ImageData(); } data.setmImageArray(new byte[2]); if (!imageDatas.contains(data)) { imageDatas.add(data);