在前面的文章中介绍了Messenger,Messenger的缺点就是一次只能处理一条消息,不支持多并发,而且只支持数据的传输,不支持方法的调用。那么在这一篇文章中 将为大家介绍更强大的IPC工具,AIDL。
AIDL 全称为Android Interface Definition Language,安卓接口定义语言,也是Android实现IPC的方式之一。接下来将为大家介绍AIDL的使用。
服务端:
服务端需要创建一个Service监听客户端的连接,并创建AIDL文件,将暴漏给客户端的方法在这个文件中声明。最后在Service中实现AIDL中的方法。
客户端:
绑定服务端的Service,并将Binder对象转欢为AIDL的接口类型。
首先我们创建一个AIDL接口(Android Studio中通过New-> AIDL-> aidl file)
import com.ipc.www.Book;//必须显式import
interface IBookManager {
List<Book> getBookList();
void addBook(in Book book);
}
根据上面的代码,AIDL中实现了两个方法,获取Book列表和添加Book,
这里需要注意的有两点:
1、Book为实现了Parcelable的实体类。需要注意的是Book类必须import进来,无论是否在同一个包中。
2、在AIDL文件的接口方法中,如果参数为实现了Parcelable的接口类的话,参数必须标注方向,in、out、inout。
Book.class
public class Book implements Parcelable {
private int bookId;
private String bookName;
public Book(int bookId,String bookName){
this.bookId = bookId;
this.bookName = bookName;
}
protected Book(Parcel in) {
bookId = in.readInt();
bookName = in.readString();
}
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(bookId);
parcel.writeString(bookName);
}
@Override
public String toString() {
return "Book{" +
"bookId=" + bookId +
", bookName='" + bookName + '\'' +
'}';
}
}
另外,如果AIDL文件中用到了自定义的Parcelable对象时,则必须创建和他同名的AIDL文件,并声明为Parcelable类型,例如Book类,Book.aidl 代码如下。
parcelable Book;
至此AIDL文件已经创建完毕,接下来看服务端的实现。
public class BookManagerService extends Service {
private static final String Tag = "BookManagerService";
//bookList
private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();
// 创建Binder 实现IBookManager AIDL中的方法 并通过OnBind返回这个binder
private Binder mBinder = new IBookManager.Stub() {
@Override
public List<Book> getBookList() throws RemoteException {
return mBookList;
}
@Override
public void addBook(Book book) throws RemoteException {
mBookList.add(book);
Log.i(Tag,mBookList.toString());
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
客户端的实现。
public class AidlActivity extends AppCompatActivity {
private static final String Tag = "AidlActivity";
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//将Binder 转换为AIDL的接口类型 即可调用aidl中的方法
IBookManager bookManager = IBookManager.Stub.asInterface(iBinder);
try {
//添加一本书
Book book = new Book(1,"我是一本书");
bookManager.addBook(book);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aidl);
//绑定Service
Intent intent = new Intent(this, BookManagerService.class);
bindService(intent,mConnection, Context.BIND_AUTO_CREATE);
}
}
运行上述代码,可以看到控制台中成功输出了我们添加的内容(图1)。

细心的小伙伴可能会问了,为什么mBookList使用CopyOnWriteArrayList而不用List呢?
这是因为CopyOnWriteArrayList支持高效率并发且是线程安全的,在AIDL中,难免会存在多线程同时访问的情况,所以在AIDL的方法中就需要做线程同步,而使用CopyOnWriteArrayList恰恰为我们省去了这部分工作。
AIDL中传输数据都支持哪些类型呢?
1、基本数据类型;
2、String和CharSequence;
3、ArrayList,HashMap,且其中的每个元素必须能够被AIDL支持。
4、实现了Parcelable的对象。
5、AIDL接口本身。
网友评论