使用AIDL
Posted blueberry_mu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用AIDL相关的知识,希望对你有一定的参考价值。
转载请注明出处: http://blog.csdn.net/a992036795/article/details/51579711
一、什么是aidl?
AIDL是android内部一种进程通信接口的描述语言。
二、使用aidl
aidl支持的数据类型:
- 基本数据类型 (int 、long、char 、boolean、double 等)
- String 和CharSequence
- List:只支持ArrayList,里面每个元素都必须能够被AIDL支持。
- Map:只支持HashMap,里面的每个元素都必须被AIDL支持,包括key和value.
- Pracelable,所有实现Pracelable接口的对象。
AIDL:所有的AIDL接口本身也可以在aidl文件中使用。
我们来写一个例子:假设服务端是一个图书馆,用来管理图书。而客户端用来添加书籍,和获得所有图书信息。
那么首先我们需要一个类来用来描述图书信息,其次我们的这个类必须实现Parcelable接口,因为要夸进程传输。
所以就有Book.java定义如下:
package com.blueberry.aidl;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by blueberry on 2016/6/3.
*/
public class Book implements Parcelable{
public int bookId ;
public String bookName ;
protected Book(Parcel in) {
bookId = in.readInt();
bookName = in.readString();
}
public Book() {
}
public Book(String bookName, int bookId) {
this.bookName = bookName;
this.bookId = bookId;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(bookId);
dest.writeString(bookName);
}
@Override
public String toString() {
return "Book{" +
"bookId=" + bookId +
", bookName='" + bookName + '\\'' +
'}';
}
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];
}
};
}
注意其中必须重写writeToParcel()方法,以及必须要有一个内部类CREATOR用来反序列化。
下面我们创建Book对应的aidl文件,来声明Book类。
Book.aidl文件:
// Book.aidl
package com.blueberry.aidl;
//声明Book
parcelable Book ;
接着我们需要一个BookManager接口来实现客户端对服务端的调用
IBookManager.aidl:
// IBookManager.aidl
package com.blueberry.aidl;
//即使在同一个包下也要声明
import com.blueberry.aidl.Book;
import com.blueberry.aidl.OnBookArrivedListener;
interface IBookManager {
/**
* 获得Books,实际传递的是ArrayList
*/
List<Book> getBookList();
/**
* 添加Book
*/
void addBook(in Book book);
}
注意 addBook()方法 java中接口的参数声明多一个描述符,in,来描述参数传递的方向,可以为in ,out或者 inout。in表示输入型参数,out表示输出型参数,inout表示输入输出参数。另外aidl接口描述中,不支持声明静态常量,这一点区别于传统的接口。
那么aidl文件写完了,我们编译一下看看,对应的文件夹下生成的java,文件
我这里先全部贴出:
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: E:\\\\AsWorkSpace\\\\test\\\\test04\\\\app\\\\src\\\\main\\\\aidl\\\\com\\\\blueberry\\\\aidl\\\\IBookManager.aidl
*/
package com.blueberry.aidl;
public interface IBookManager extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.blueberry.aidl.IBookManager {
private static final java.lang.String DESCRIPTOR = "com.blueberry.aidl.IBookManager";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.blueberry.aidl.IBookManager interface,
* generating a proxy if needed.
*/
public static com.blueberry.aidl.IBookManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.blueberry.aidl.IBookManager))) {
return ((com.blueberry.aidl.IBookManager) iin);
}
return new com.blueberry.aidl.IBookManager.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getBookList: {
data.enforceInterface(DESCRIPTOR);
java.util.List<com.blueberry.aidl.Book> _result = this.getBookList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addBook: {
data.enforceInterface(DESCRIPTOR);
com.blueberry.aidl.Book _arg0;
if ((0 != data.readInt())) {
_arg0 = com.blueberry.aidl.Book.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addBook(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.blueberry.aidl.IBookManager {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
/**
* 获得Books,实际传递的是ArrayList
*/
@Override
public java.util.List<com.blueberry.aidl.Book> getBookList() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<com.blueberry.aidl.Book> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(com.blueberry.aidl.Book.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
/**
* 添加Book
*/
@Override
public void addBook(com.blueberry.aidl.Book book) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((book != null)) {
_data.writeInt(1);
book.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
/**
* 获得Books,实际传递的是ArrayList
*/
public java.util.List<com.blueberry.aidl.Book> getBookList() throws android.os.RemoteException;
/**
* 添加Book
*/
public void addBook(com.blueberry.aidl.Book book) throws android.os.RemoteException;
}
可以看到这个文件主要有一个接口(IBookManager)和2个实现类(Stub、Proxy)。
我们可以看到 IBookManager实际就是我们在aidl文件中定义的那个接口,只是它继承了一个IInterface接口。看看IInterface接口的描述:
/**
* Base class for Binder interfaces. When defining a new interface,
* you must derive it from IInterface.
*/
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();
}
可以看到使用binder通信,每个接口都必须继承自这个接口 。
我们现在来看Stub类的定义:
public static abstract class Stub extends android.os.Binder implements com.blueberry.aidl.IBookManager {
private static final java.lang.String DESCRIPTOR = "com.blueberry.aidl.IBookManager";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.blueberry.aidl.IBookManager interface,
* generating a proxy if needed.
*/
public static com.blueberry.aidl.IBookManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.blueberry.aidl.IBookManager))) {
return ((com.blueberry.aidl.IBookManager) iin);
}
return new com.blueberry.aidl.IBookManager.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getBookList: {
data.enforceInterface(DESCRIPTOR);
java.util.List<com.blueberry.aidl.Book> _result = this.getBookList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addBook: {
data.enforceInterface(DESCRIPTOR);
com.blueberry.aidl.Book _arg0;
if ((0 != data.readInt())) {
_arg0 = com.blueberry.aidl.Book.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addBook(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
}
static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
可以看到它继承自Binder,并实现了IBookManager的asBinder()方法,但并没有实现IBookManager的addBook()和getBookList()方法,这些犯法最终留给他的子类去是实现。
首先,看他的的构造方法:
private static final java.lang.String DESCRIPTOR = "com.blueberry.aidl.IBookManager";
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
它将调用父类binder的 attachInterface方法,将自身,以及他的描述符传递类进去。我们可以看看这个方法的定义:
/**
* Convenience method for associating a specific interface with the Binder.
* After calling, queryLocalInterface() will be implemented for you
* to return the given owner IInterface when the corresponding
* descriptor is requested.
*/
public void attachInterface(IInterface owner, String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
这里的大致意思是:调用这个方法之后,我们到时可以使用queryLocalnterface()这个方法传入描述符DESTRIPTOR来找到这个binder.
所以紧接着就有这个方法:
/**
* Cast an IBinder object into an com.blueberry.aidl.IBookManager interface,
* generating a proxy if needed.
*/
public static com.blueberry.aidl.IBookManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.blueberry.aidl.IBookManager))) {
return ((com.blueberry.aidl.IBookManager) iin);
}
return new com.blueberry.aidl.IBookManager.Stub.Proxy(obj);
}
这里调用queryLocalInterface()来查询本地是否有这个binder.如果有的话,就将本地的这个binder返回,否则的话将使用 这个binder对象构造出一个代理类Proxy返回。
这里就说明了如果本地有这个binder,就使用本地的这个binder。否则这个binder就是远程的,那我就将这个binder作为参数构造出一个代理类Proxy来使用。
那我们就先放下onTransact()方法,来看Proxy类。实际上onTransact()方法实在夸进程调时才会调用,而且实在服务端被调用。
我们先看Proxy类:
private static class Proxy implements com.blueberry.aidl.IBookManager {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
/**
* 获得Books,实际传递的是ArrayList
*/
@Override
public java.util.List<com.blueberry.aidl.Book> getBookList() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<com.blueberry.aidl.Book> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(com.blueberry.aidl.Book.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
/**
* 添加Book
*/
@Override
public void addBook(com.blueberry.aidl.Book book) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((book != null)) {
_data.writeInt(1);
book.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
这个很明显是一个代理模式,在构造方法将被代理的类传递进来,然后真正是在执行这个类的方法,实际就是执行mRemote的方法。
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
我们接着来看他的 getBookList()方法和addBook()方法
/**
* 获得Books,实际传递的是ArrayList
*/
@Override
public java.util.List<com.blueberry.aidl.Book> getBookList() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<com.blueberry.aidl.Book> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(com.blueberry.aidl.Book.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
/**
* 添加Book
*/
@Override
public void addBook(com.blueberry.aidl.Book book) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((book != null)) {
_data.writeInt(1);
book.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
我们可以看到,他使用Parcel创建 出输入参数,以及返回参数最后是调用了被代理类即 mRemote的 transact方法。因为这个mRemote是远程服务端传递过来的。
所以这个方法的调用执行将发生在服务端。
我们来看一下这个方法子在Binder中的定义:
/**
* Default implementation rewinds the parcels and calls onTransact. On
* the remote side, transact calls into the binder to do the IPC.
*/
public final boolean transact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
我们可以看到最后执行了 它的onTransact()方法。
那么,现在我们就明白了。因为服务端和客户端有着同样的aidl文件,这个远程对象实际是 服务端那边声明的Stub类,它将执行的是Stub类中onTransact()方法
那么我们就来看,Stub类中的onTransact()方法:
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getBookList: {
data.enforceInterface(DESCRIPTOR);
java.util.List<com.blueberry.aidl.Book> _result = this.getBookList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addBook: {
data.enforceInterface(DESCRIPTOR);
com.blueberry.aidl.Book _arg0;
if ((0 != data.readInt())) {
_arg0 = com.blueberry.aidl.Book.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addBook(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
可以看到,他最终调用了服务端Stub的 addBook()方法以及getBookList()方法。
这2个方法最后发生在服务端。
这样就完成了一次原生调用。
三、接着我贴一下服务端Service的实现,以及客户端的调用。
public class SimpleService extends Service {
private static final String TAG = "SimpleService";
private CopyOnWriteArrayList<Book> books = new CopyOnWriteArrayList<>();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new IBookManager.Stub(){
@Override
public List<Book> getBookList() throws RemoteException {
Log.i(TAG, "getBookList: books: " +books);
Log.i(TAG, "current Thread :" +Thread.currentThread());
return books;
}
@Override
public void addBook(Book book) throws RemoteException {
Log.i(TAG, "addBook: book: "+book);
Log.i(TAG, "current Thread :"+Thread.currentThread());
books.add(book);
}
};
}
}
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private Button btnAdd,btnGet;
private TextView tvLog;
private int count;
private IBookManager mBookManager;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBookManager = IBookManager.Stub.asInterface(service) ;
Log.i(TAG, "onServiceConnected: ");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected: ");
}
} ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,SimpleService.class);
bindService(intent,conn, Context.BIND_AUTO_CREATE);
initView();
}
private void initView() {
btnAdd = (Button) findViewById(R.id.btn_add);
btnGet = (Button) findViewById(R.id.btn_get);
tvLog = (TextView) findViewById(R.id.tv_log);
btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Book book = new Book(count,"book#"+count);
count++;
try {
mBookManager.addBook(book);
} catch (RemoteException e) {
e.printStackTrace();
}
Log.i(TAG, "add book :"+book);
Log.i(TAG, "current thread: "+Thread.currentThread());
}
});
btnGet.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
List<Book> books = mBookManager.getBookList();
Log.i(TAG, "books :"+books);
Log.i(TAG, "current thread: "+Thread.currentThread());
tvLog.setText("");
for(Book book:books){
tvLog.append(book.toString());
tvLog.append("\\n");
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
}
四、可以为binder设置死亡代理,这样在binder销毁之后我们就可以接受到消息。
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.i(TAG, "binderDied: ");
}
} ;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBookManager = IBookManager.Stub.asInterface(service) ;
try {
/*设置死亡代理*/
service.linkToDeath(mDeathRecipient ,0 );
} catch (RemoteException e) {
e.printStackTrace();
}
Log.i(TAG, "onServiceConnected: ");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected: ");
}
} ;
五、最后在扩展一个
假如我们不想每次都使用getBookList来获取图书列表,我们希望客户端可以在服务端设置一个监听器。使得客户端可以接受服务端的消息回调。
那么我们就需要定义一个接口来定义回调方法,因为是夸进程所以我们需要使用aidl文件来定义。
// OnBookArrivedListener.aidl
package com.blueberry.aidl;
// Declare any non-default types here with import statements
import com.blueberry.aidl.Book;
interface OnBookArrivedListener {
void onBookArrived(in Book book) ;
}
还需要在IBookManager.aidl添加2个方法用来 注册观察着,和移除观察者。
// IBookManager.aidl
package com.blueberry.aidl;
//即使在同一个包下也要声明
import com.blueberry.aidl.Book;
import com.blueberry.aidl.OnBookArrivedListener;
interface IBookManager {
/**
* 获得Books,实际传递的是ArrayList
*/
List<Book> getBookList();
/**
* 添加Book
*/
void addBook(in Book book);
/**
* 添加监听器
*/
void registerListener(in OnBookArrivedListener listener) ;
/**
* 移除监听器
*/
void remoteListener(in OnBookArrivedListener listener);
}
同样我们需要在服务端 用一个容器来存储这些观察者。
package com.blueberry.test04;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;
import com.blueberry.aidl.Book;
import com.blueberry.aidl.IBookManager;
import com.blueberry.aidl.OnBookArrivedListener;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class SimpleService extends Service {
private static final String TAG = "SimpleService";
/*最终会将CopyOnWriteArrayList转化为ArrayList进行夸进程传输*/
private CopyOnWriteArrayList<Book> books = new CopyOnWriteArrayList<>() ;
/**
* RemoteCallbackList
*/
private RemoteCallbackList<OnBookArrivedListener> listeners = new RemoteCallbackList<>() ;
private IBookManager.Stub stub =new IBookManager.Stub(){
@Override
public List<Book> getBookList() throws RemoteException {
Log.i(TAG, "current thread: "+Thread.currentThread());
Log.i(TAG, "getBookList: Books.class: "+books.getClass());
return books;
}
@Override
public void addBook(Book book) throws RemoteException {
Log.i(TAG, "current thread: "+Thread.currentThread());
Log.i(TAG, "addBook: book: "+book);
books.add(book) ;
int N = listeners.beginBroadcast();
for (int i = 0; i < N; i++) {
OnBookArrivedListener broadcastItem = listeners.getBroadcastItem(i);
if(broadcastItem!=null){
try {
broadcastItem.onBookArrived(book);
}catch (RemoteException e){
e.printStackTrace();
}
}
}
listeners.finishBroadcast();
}
@Override
public void registerListener(OnBookArrivedListener listener) throws RemoteException {
listeners.register(listener) ;
}
@Override
public void remoteListener(OnBookArrivedListener listener) throws RemoteException {
listeners.unregister(listener);
Log.i(TAG, "remoteListener: ok.");
}
};
public SimpleService() {
}
private int count = 0;
@Override
public IBinder onBind(Intent intent) {
new Thread(){
@Override
public void run() {
while (true){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Book book = new Book("book#"+count,count);
count++ ;
try {
stub.addBook(book);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}.start();
return stub ;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy: ");
}
}
注意我并没有使用CopyOnWriteArrayList来存储观察着们,原因是:
如果使用这种集合,我们在取消注册观察者即调用remoteListener(OnBookArrivedListener listener)将会无作用,会因为这个参数中传递过来的对象,在跨进程时将会被序列化,以及反序列化。将导致和服务端的不是同一个对象,所以不会移除的这个监听器。
所以我们选择使用RemoteCallbackList 来存储。RemoteCallbakList使用一个ArrayMap< IBinder, Callback> 来存数这些监听着们。
我们来看一下它的register方法 和remove方法
*/
public boolean register(E callback, Object cookie) {
synchronized (mCallbacks) {
if (mKilled) {
return false;
}
IBinder binder = callback.asBinder();
try {
Callback cb = new Callback(callback, cookie);
binder.linkToDeath(cb, 0);
mCallbacks.put(binder, cb);
return true;
} catch (RemoteException e) {
return false;
}
}
}
public boolean unregister(E callback) {
synchronized (mCallbacks) {
Callback cb = mCallbacks.remove(callback.asBinder());
if (cb != null) {
cb.mCallback.asBinder().unlinkToDeath(cb, 0);
return true;
}
return false;
}
}
可以看到它调用监听器的 asBinder()方法作为键来存储对象,
我们上文分析过Stub、和Proxy类,知道Stub返回的 this, Proxy返回的是mRemote。 而如果是夸进程时,这个mRemote正时服务端Stub返回的this.
所以这种方法可行。
以上是关于使用AIDL的主要内容,如果未能解决你的问题,请参考以下文章