首先进程间通讯的方式有:广播,ContentProvider(内容提供者),AIDL(Android接口定义语言)
今天我们所讲的就是AIDL:
首先定义AIDL接口文件,如果进程间要传递对象,那么这个对象必须实现Praceable接口:
// Book.aidl
package com.example.aidl;
parcelable Book;
远程服务端的方法,当图书变化的时候通知给监听者
package com.example.aidl;
import com.example.aidl.Book;
import com.example.aidl.IOnNewBookArriverdListener;
interface IBookManager {
List<Book> getBookList();
void addBock(in Book book);
void registerListener(IOnNewBookArriverdListener listener);
void unregisterListener(IOnNewBookArriverdListener listener);
}
监听器接口
package com.example.aidl;
import com.example.aidl.Book;
interface IOnNewBookArriverdListener {
void onNewBookArrived(in Book newBook);
}
Book类,注意:Book类所在的包名
package com.example.aidl;
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable {
private int no = 0;
private String name;
public Book(int no, String name) {
this.no = no;
this.name = name;
}
protected Book(Parcel in) {
no = in.readInt();
name = 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];
}
};
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(no);
dest.writeString(name);
}
@Override
public String toString() {
return "Book{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
}
服务端需要注意的是:存储监听器的类是RemoteCallbackList
package com.example.service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import com.example.aidl.Book;
import com.example.aidl.IBookManager;
import com.example.aidl.IOnNewBookArriverdListener;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
public class BookManagerService extends Service {
private static final String TAG = "BookManagerService";
private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();
// 这种写法,当解绑服务的时候,服务端竟然无法找到我们之前注册的那个listener,在客户端我们注册和解注册的时候
// 明明传递的是同一个 Listener啊!,最终服务端无法找到要解除的listener,而宣告失败,这当然不是我们想要的结果.
// 因为Binder会把客户端传递过来的对象重新转化并生成一个新的对象,虽然我们注册和解注册的过程传递的是同一个对象
// 但是,通过Binder传递到服务端之后,却会产生两个全新的对象,别忘了对象是不能跨进程传递的,对象的跨进程传递本质上
// 反序列化的过程,这就是为什么AIDL中的自定义对象都必须要实现Parcelable接口的原因,
// 那么我们如何才能实现解注册的功能呢?答案是 RemoteCallbackList,
// private CopyOnWriteArrayList<IOnNewBookArriverdListener> mListenerList = new CopyOnWriteArrayList<>();
private RemoteCallbackList<IOnNewBookArriverdListener> mListenerList = new RemoteCallbackList<>();
public BookManagerService() {
}
private void onNewBookArrived(Book book) throws RemoteException {
mBookList.add(book);
System.out.println("lgj service mBookList size:" + mBookList.size());
// for (int i = 0; i < mListenerList.size(); i++) {
// IOnNewBookArriverdListener listener = mListenerList.get(i);
// listener.onNewBookArrived(book);
// }
int N = mListenerList.beginBroadcast();
for (int i = 0; i < N; i++) {
IOnNewBookArriverdListener broadcastItem = mListenerList.getBroadcastItem(i);
if (broadcastItem != null) {
broadcastItem.onNewBookArrived(book);
}
}
mListenerList.finishBroadcast();
}
private Binder mBinder = new IBookManager.Stub() {
@Override
public List<Book> getBookList() throws RemoteException {
System.out.println("lgj service Binder pid:" + android.os.Process.myPid() + " tid:" + Process.myTid());
return mBookList;
}
@Override
public void addBock(Book book) throws RemoteException {
mBookList.add(book);
}
@Override
public void registerListener(IOnNewBookArriverdListener listener) throws RemoteException {
// if (!mListenerList.contains(listener)){
// mListenerList.add(listener);
// }else {
// System.out.println(TAG + "lgj already exists...");
// }
// System.out.println(TAG + "lgj service register listener size :" +mListenerList.size() );
mListenerList.register(listener);
System.out.println(TAG + "lgj service register listener size :" + mListenerList.getRegisteredCallbackCount());
}
@Override
public void unregisterListener(IOnNewBookArriverdListener listener) throws RemoteException {
// if (mListenerList.contains(listener)){
// mListenerList.remove(listener);
// }else {
// System.out.println(TAG + "lgj service not found,can not unregister...");
// }
// System.out.println(TAG + "lgj service unregister listener size :" +mListenerList.size());
mListenerList.unregister(listener);
System.out.println(TAG + "lgj service unregister listener size :" + mListenerList.getRegisteredCallbackCount());
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public void onDestroy() {
super.onDestroy();
System.out.println("lgj service BookManagerService onDestroy...");
mIsServiceDestoryed.set(true);
}
private AtomicBoolean mIsServiceDestoryed = new AtomicBoolean(false);
@Override
public void onCreate() {
super.onCreate();
// 模拟每隔5秒钟图书发生变化
new Thread(new Runnable() {
@Override
public void run() {
while (!mIsServiceDestoryed.get()) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
int bookId = mBookList.size() + 1;
Book book = new Book(bookId, "new book#" + bookId);
try {
onNewBookArrived(book);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
客户端代码:
Intent intent = new Intent(this, BookManagerService.class);
// startService(intent); 长期运行在后台,
// 如果只是简单的bind没有start的话,那么退出Activity 服务也会随之而停止,
// 我理解Activity绑定服务的话,随着Activity的存在即服务而存在,随着Activity的销毁服务则停止
// (即使你在Activity的onDestroy方法中没有调用unbindService() 这个方法,服务也会停止)
bindService(intent,connection, Context.BIND_AUTO_CREATE);
private IOnNewBookArriverdListener mListener = new IOnNewBookArriverdListener.Stub() {
@Override
public void onNewBookArrived(Book newBook) throws RemoteException {
System.out.println("lgj xinshu : " + newBook.getName());
}
};
public IBookManager mBookManager;
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBookManager = IBookManager.Stub.asInterface(service);
if (mBookManager != null){
try {
//添加注册监听实例对象
mBookManager.registerListener(mListener);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
注意ondestroy记得取消注册监听
@Override
protected void onDestroy() {
try {
mBookManager.unregisterListener(mListener);
} catch (RemoteException e) {
e.printStackTrace();
}
// unbindService(connection);
super.onDestroy();
}