前言
关于AIDL的原理以及详细介绍,我在Binder机制原理一文中有讲到,这里就不再赘述。本篇文章以实战为核心,写一个AIDL操作实例出来
AIDL与Messenger的区别就是AIDL支持并发处理请求,也就是多进程,多线程的情况。而Messenger是多进程,单线程
demo的github地址:https://github.com/LJHnb666666/AIDLDemo
1.实现思路
还是需要客户端,服务端Service。除此之外,还需要一个实体类做客户端和服务端交互的Bean,还需要AIDL文件定义操作的接口。
demo结构如图
2.具体步骤
①写实体类Book
这里需要注意,Book必须实现Parcelable 接口,标明其是可序列化的。
public class Book implements Parcelable {
String name;
int cost;
public Book(String name, int cost) {
this.name = name;
this.cost = cost;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", cost=" + cost +
'}';
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(cost);
}
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 in){
this.name = in.readString();
this.cost = in.readInt();
}
}
②写AIDL,定义接口
注意: (1)如果要在AIDL 接口文件中使用自定义的Parcelable 对象或者AIDL 对象,必须显式的 import 进来,即使它们在同一个包内。 (2)如果在AIDL 接口文件用到了Parcelable 对象,必须新建一个和它同名的AIDL 文件,并在其中声明它为parcelable 类型
所以我这边要创建两个AIDL 文件,一个是定义接口,一个是与Book同名的AIDL 文件
IBookManager.aidl
import com.example.aidldemo.Book;
interface IBookManager {
void addBook(in Book book);
List<Book> getBookList();
}
Book.aidl
parcelable Book;
③服务端Service
主要就是创建IBookManager.Stub 对象,并重写接口里面的方法。同时通过onBind 方法把IBookManager.Stub 对象返回
public class MyService extends Service {
private CopyOnWriteArrayList<Book> bookList;
public MyService(){
bookList = new CopyOnWriteArrayList<>();
}
private IBookManager.Stub stub = new IBookManager.Stub() {
@Override
public void addBook(Book book) throws RemoteException {
Log.v("ljh","这里是Service,新增的书为" + book);
bookList.add(book);
}
@Override
public List<Book> getBookList() throws RemoteException {
return bookList;
}
};
@Override
public IBinder onBind(Intent intent) {
return stub;
}
}
④客户端
主要就是根据ServiceConnection 返回的Binder 对象,调用IBookManager.Stub.asInterface() 方法,给IBookManager 接口赋值,从而进行进程间通信
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button connect;
Button addBook;
Button getBooks;
IBookManager iBookManager;
ServiceConnection serviceConnection;
Boolean isBind;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
isBind = false;
connect = findViewById(R.id.btn_bindService);
addBook = findViewById(R.id.btn_addBook);
getBooks = findViewById(R.id.btn_getBooks);
connect.setOnClickListener(this::onClick);
addBook.setOnClickListener(this::onClick);
getBooks.setOnClickListener(this::onClick);
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.v("ljh","这里是客户端,与Service连接成功");
iBookManager = IBookManager.Stub.asInterface(service);
isBind = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.v("ljh","这里是客户端,与Service断开连接");
}
};
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_bindService:
bindService(new Intent(MainActivity.this,MyService.class),serviceConnection, Context.BIND_AUTO_CREATE);
break;
case R.id.btn_addBook:
try {
iBookManager.addBook(new Book("新书",10));
} catch (RemoteException e) {
e.printStackTrace();
}
break;
case R.id.btn_getBooks:
try {
List<Book> bookList = iBookManager.getBookList();
Log.v("ljh","这里是客户端,从Service获取的书的集合为:"+ bookList);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
break;
}
}
@Override
protected void onStop() {
super.onStop();
if(isBind){
unbindService(serviceConnection);
isBind = false;
}
}
}
3.项目地址和文章推荐
项目地址:https://github.com/LJHnb666666/AIDLDemo 好文推荐:https://juejin.cn/post/7024376277436121118#heading-1
|