一、概述
AIDL是Android Interface Definition Language的缩写,即Android接口定义语言。它是Android的进程间通信比较常用的一种方式。
Android中,每一个进程都有自己的Dalvik VM实例,拥有自己的独立的内存空间,进程与进程之间不共享内存,这就产生了进程间通信的需求。
二、语法
AIDL是Android接口定义语言,是一门语言,所以它拥有自己的语法和特性。
(一)数据类型
AIDL支持的数据类型包括以下几种:
- Java的8种基本数据类型:int,short,long,char,double,byte,float,boolean;
- CharSequence类型,如String、SpannableString等;
- ArrayList
,并且T必须是AIDL所支持的数据类型; - HashMap<K,V>,并且K和V必须是AIDL所支持的数据类型;
- 所有Parceable接口的实现类,因为跨进程传输对象时,本质上是序列化与反序列化的过程;
- AIDL接口,所有的AIDL接口本身也可以作为可支持的数据类型;
有两个需要注意的地方:
1、在Java中,如果一个对象和引用它的类在同一个package下,是不需要导包的,即不需要import,而在AIDL中,自定义的Parceable对象和AIDL接口定义的对象必须在所引用的AIDL文件中显式import进来,不管这些对象和所引用它们的AIDL文件是否在同一个包下。
2、如果AIDL文件中使用到自定义的Parceable对象,则必须再创建一个与Parceable对象同名的AIDL文件,声明该对象为Parceable类型,并且根据上一条语法规定,在AIDL文件中进行显式import。
(二)文件类型
- 所有AIDL文件都是以.aidl作为后缀的;
- 根据用途区分,AIDL文件的有两种,一种是用于定义接口,另一种是用于声明parceable对象,以供其他AIDL文件使用;
(三)定向tag
AIDL中,除了基本数据类型,其他类型的方法参数都必须标上数据在跨进程通信中的流向:in、out或inout:
1、in表示输入型参数:只能由客户端流向服务端,服务端收到该参数对象的完整数据,但服务端对该对象的后续修改不会影响到客户端传入的参数对象;
2、out表示输出型参数:只能由服务端流向客户端,服务端收到该参数的空对象,服务端对该对象的后续修改将同步改动到客户端的相应参数对象;
3、inout表示输入输出型参数:可在客户端与服务端双向流动,服务端接收到该参数对象的完整数据,且服务端对该对象的后续修改将同步改动到客户端的相应参数对象;
定向tag需要一定的开销,根据实际需要去确定选择什么tag,不能滥用。
深入理解tag:你真的理解AIDL中的in,out,inout么?
(四)其他
1、所有AIDL接口都是继承自IInterface
接口的,IInterface
接口中只声明了一个asBinder
方法:
public interface IInterface
{
/**
* Retrieve the Binder object associated with this interface.
* You must use this instead of a plain cast, so that proxy objects
* can return the correct result.
*/
public IBinder asBinder();
}
2、系统会帮我们为所有用于定义接口的AIDL文件生成相应的java代码,手写这份java代码与用AIDL系统生成实际上是一样的,AIDL可以方便系统为我们生成固定格式的java代码。
三、基本用法
在AndroidStudio中工程目录的Android视图下,右键new一个AIDL文件,默认将创建一个与java
文件夹同级的aidl
文件夹用于存放AIDL文件,且aidl
文件夹下的包名与build.gradle中配置的applicationId
一致,而applicationId
默认值是应用的包名。
AIDL的底层是基于Binder实现的,而Binder机制也是一种请求-响应式的通信模型,请求方一般称为Client,响应方称为Server。
Demo介绍:在一个应用内部新起一个进程作为服务端,服务端提供addStudent和getStudentList两个方法,分别用于客户端向服务端添加Student数据和获取Student列表,Student是自定义对象,只有id和name两个属性。源码下载链接。
(一)服务端
新建AIDL文件,定义一个接口,在这个接口里声明两个方法,分别用于添加Student数据和获取所有Student数据,因为AIDL是接口定义语言,所以不能在AIDL文件里对方法进行实现:
/aidl/com/sqchen/aidltest/IStudentService.aidl
package com.sqchen.aidltest;
//显式import
import com.sqchen.aidltest.Student;
interface IStudentService {
List<Student> getStudentList();
//定向tag
void addStudent(in Student student);
}
因为IStudentService.aidl
接口中使用到的Student
是自定义对象,不属于Java基本数据类型和CharSequence类型,所以按照语法规定,在IStudentService.aidl
中需要显式import,同时我们要让Student实现Parceable接口,并且新建一个AIDL文件用于声明Student类是Parceable类型:
/aidl/com/sqchen/aidltest/Student.java
public class Student implements Parcelable {
private int id;
private String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(name);
}
public void readFromParcel(Parcel parcel) {
this.id = parcel.readInt();
this.name = parcel.readString();
}
public static Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>() {
@Override
public Student createFromParcel(Parce