在看Binder的时候就非常好奇AIDL这个神奇的东西,为什么我写了.aidl文件,AS就自动生成了与它对应的文件,而且还实现它里面的方法。首先还是要知道AIDL是什么。。。
关于AIDL
AIDL,英文全称:Android Interface Definition Language。很直白的翻译的话就是安卓接口定义语言。它是一种语言,可以拿来生成用于IPC的代码。其实,可以把AIDL理解称为一个模板,在使用中,实际上起作用的不是AIDL代码,而是根据它生成的一个IInterface实例的代码。
在AIDL文件中并不是所有的数据类型都是可以使用的。下面是它可以使用的数据类型:
- 基本数据类型:int short long float double byte boolean char
- String和CharSequence
- List:只支持ArrayList,里面的每个元素都必须能够被AIDL支持
- Map:只支持HashMap,里面的每个元素都必须能够被AIDL支持,包括key和value
- Parcelable:所有实现了Parcelable接口的对象
- AIDL:所有的AIDL接口本身也可以在AIDL文件中使用
注意
- 自定义的Parcelable对象和AIDL对象必须要显式import进来
- 如果AIDL文件中用到了自定义的Parcelable对象,那么必须新建一个和它同名的AIDL文件,并在其中声明为Parcelable类型
- AIDL中除了基本数据类型,其它类型必须标上方向
- in 输入型参数
- on 输出型参数
- inout 输入输出型参数
- AIDL接口中只支持方法,不支持声明静态变量。
AIDL进程间通信
- 远程服务端
public class BookManagerService extends Service {
private static final String TAG = "BMS";
//支持并发读/写,可以进行自动的线程同步
private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();
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);
}
}
@Override
public void onCreate() {
super.onCreate();
mBookList.add(new Book(1,"Android"));
mBookList.add(new Book(2,"Web"));
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG,"onBind()");
return mBinder;
}
}
实现步骤:
- 通过IBookManager.Stub创建Binder对象,实现IBookManager接口中的两个方法getBookList和addBook
- onBind方法返回IBinder对象
这里用到了CopyOnWriteArrayList,刚才说AIDL支持的数据类型List只支持ArrayList,但CopyOnWriteArrayList并不继承于持ArrayList。因为AIDL支持的是抽象的List,且List只是一个接口。Binder会按照List的规范去访问数据并最终形成一个ArrayList传递给客户端。相似的还有ConcurrentHasMap
客户端实现
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IBookManager bookManager = IBookManager.Stub.asInterface(service);
try {
List<Book> bookList = bookManager.getBookList();
Log.e(TAG,"query book list,list type:"+bookList.getClass().getCanonicalName());
Log.e(TAG,"query book list:"+bookList.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,BookManagerService.class);
bindService(intent,mServiceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
}
}
实现步骤:
- 首先和服务端绑定bindService
- 通过服务端传递的IBinder对象,根据IBookManager中判断是本地还是远程的asInrterface方法,创建IBookManager对象
- 通过IBookManager,操作目标方法
网友评论