AIDL的使用
我们可以使用AIDL来实现跨进程的方法调用,在上一个博客中我们介绍了binder的概念,在binder的基础上我们可以更加容易的理解AIDL。这里先介绍使用aidl来进行进程间通信的流程,分为服务端和客户端两个方面。
- 服务端
服务端首先要创建一个service用来监听客户端的连接请求,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明,最后再service中实现这个AIDL接口即可。
- 客户端
客户端所要做的事情就稍微简单一些,首先需要绑定服务端的setvice,绑定成功后,将服务端返回的binder对象转成AIDL接口所属的类型,接着就可以调用AIDL中的方法了。
上述只是一个感性的过程,AIDL的实现过程远不止这么简单,接下来会对其中的细节和难点进行详细介绍。
3.AIDL接口的创建
首先看AIDL接口的创建,如下所示,我们创建了一个后缀为AIDL的文件,在里面生命了一个接口和两个接口方法。
// IbookManager.aidl
package com.dzx.recyclerviewdemo.aidl;
// Declare any non-default types here with import statements
import com.dzx.recyclerviewdemo.aidl.Book;
interface IbookManager {
/**
* 除了基本数据类型,其他类型的参数都需要标上方向类型:in(输入), out(输出), inout(输入输出)
*/
void addBook(in Book book);
List<Book> getBookList();
}
在AIDL文件中,并不是所有的数据类型都是可以使用的,那么到底AIDL文件支持哪些数据类型呢?
共 4 种:
- Java 的基本数据类型
- List 和 Map
- 元素必须是 AIDL 支持的数据类型
- Server 端具体的类里则必须是 ArrayList 或者 HashMap
- 其他 AIDL 生成的接口
- 实现 Parcelable 的实体
其中自定义的parcelable对象和AIDL对象必须要显式import进来,不管他们是否和当前的AIDL文件位于同一个包内。
另外一个需要注意的地方是,如果AIDL文件中用到了自定义的parcelable对象,那么必须新建一个和他同名的AIDL文件并在其中生命他为parcelable类型。在上面ibookmanager中,我们用到了book这个类,所以,必须要创建爱你book.aidl,如下
package com.dzx.recyclerviewdemo.aidl;
//还要和声明的实体类在一个包里,同时注意不要新建aidl文件,因为你会发现,新建不了,
//提示你名称唯一,此时你新建一个file,名字为Person.aidl就可以,需要特别注意下
parcelable Book;
然后还有一个实现了parcelable的book。java类,如下:
package com.dzx.recyclerviewdemo.aidl;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by Administrator on 2018/8/14 0014.
*/
public class Book implements Parcelable{
public int bookId;
public String bookName;
public Book(int bookId, String bookName) {
this.bookId = bookId;
this.bookName = bookName;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(bookId);
dest.writeString(bookName);
}
public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
@Override
public Book createFromParcel(Parcel source) {
return new Book(source);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
private Book(Parcel parcel){
bookId = parcel.readInt();
bookName = parcel.readString();
}
}
4.远程服务端service的实现
上面讲述了如何定义AIDL接口,接下来我们就需要实现这个接口了,我们创建一个MyAidlService,的service,代码如下:
public class MyAidlService extends Service {
private static final String TAG = "MyAidlService";
private CopyOnWriteArrayList<Book> mBooks;
private IBinder mIbinder = new IbookManager.Stub(){
@Override
public void addBook(Book book) throws RemoteException {
Log.e("sssssssssssssss", "ssssssssaddBook" );
mBooks.add(book);
}
@Override
public List<Book> getBookList() throws RemoteException {
return mBooks;
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
mBooks = new CopyOnWriteArrayList<>();
Log.e("sssssssssss", "ssssssssonBind" );
return mIbinder;
}
@Override
public void onCreate() {
super.onCreate();
Log.e("sssssssssss", "onDestroy" );
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e("sssssssssss", "onDestroy" );
}
}
上面这主要看getbooklist和addBook这两个aidl方法的实现,实现过程也比较简单,注意这里采用了CopyOnWriteArrayList,在前面我们提到,AIDL方法啊是在服务端的binder线程池中执行的,因此当多个客户端同时连接的时候,会存在多个线程同时访问的情形,所以我们要子啊AIDL方法中处理线程同步,所以会用到CopyOnWriteArrayList来进行自动的线程同步。
然后我们需要在XML中注册这个service,注意此service是运行在独立进程中的,它和客户端的activity不在同一个进程中,这样就构成了进程间通信的场景:
<service
android:name=".MyAidlService"
android:enabled="true"
android:exported="true"
android:process=":aidl"/>
客户端
客户端实现首先要绑定远程服务,绑定成功后将服务端返回的binder赌侠ing转成AIDL接口,然后就可以通过这个接口去调用服务端的远程方法了,代码如下:
public class MainActivity extends AppCompatActivity {
private List<String>list;
private IbookManager ibookManager;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
ibookManager = IbookManager.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(MainActivity.this,MyAidlService.class);
bindService(intent,connection, Service.BIND_AUTO_CREATE);
startService(intent);
TextView tv = (TextView)findViewById(R.id.tv);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Book book = new Book(1,"android");
try {
ibookManager.addBook(book);
List<Book>mList = ibookManager.getBookList();
Log.e("sssss","ssssssss mlist = "+mList.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
}
其实大家看起来跟同进程的没啥区别 但是这是多进程的跨进程通信,希望大家了解
本文详细介绍了使用AIDL实现Android跨进程通信的过程。包括服务端创建AIDL接口、实现服务及客户端绑定服务并调用远程方法等内容。
595

被折叠的 条评论
为什么被折叠?



