当项目AIDL业务需求增多时,我们不可能无限制得创建Service,因此,针对这种情况,我们将所有得AIDL放在同一个Service中去管理。
在这种模式下,整个工作机制是这样得:每个业务模块创建自己得AIDL接口并实现此接口,这个时候不同业务模块之间不能有耦合的,所有实现细节我们要单独开来,然后向服务端提供自己的唯一标识和其对应的Binder对象;对于服务端来说,只需要一个Service就可以了,服务端提供一个queryBinder接口,这个接口能够根据业务模块的特征来返回相应的Binder对象给它们,不同的业务模块拿到所需的Binder对象后就可以进行远程方法调用了。由此可见,Binder连接池的主要作用就是将每个业务模块的Binder请求统一转发到远程Service中去执行,从而避免了重复创建Service的过程,它的工作原理如下图:
我们先看工程目录
下面我们Binder连接池的代码实现做一下说明。首先,我们提供了两个AIDL接口(IBookManager和IAuth)来模拟上面提到的多个业务模块都要使用AIDL的情况,其中IBookManager接口提供图书管理功能,IAuth接口提供获取用户信息功能,声明如下:
// IBookManager.aidl
package com.example.binderpool.aidl;
import com.example.binderpool.aidl.Book;
import com.example.binderpool.aidl.IOnNewBookArrivedListener;
// Declare any non-default types here with import statements
interface IBookManager {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
List<Book> getBookList();
void addBook(in Book book);
void registerListener(IOnNewBookArrivedListener listener);
void unregisterListener(IOnNewBookArrivedListener listener);
}
// IAuth.aidl
package com.example.binderpool.aidl;
import com.example.binderpool.aidl.User;
// Declare any non-default types here with import statements
interface IAuth {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
User getCurrentUser();
}
接下来看两个接口的实现:
public class BookManagerImpl extends IBookManager.Stub {
//CopyOnWriteArrayList支持并发读/写
private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();
//private CopyOnWriteArrayList<IOnNewBookArrivedListener> mListenerList = new CopyOnWriteArrayList<>();
//当客户端进程终止后,RemoteCallbackList能够自动移除客户端所注册的listener。
//RemoteCallbackList内部自动实现了线程同步的功能
private RemoteCallbackList<IOnNewBookArrivedListener> mListenerList = new RemoteCallbackList<>();
@Override
public List<Book> getBookList() throws RemoteException {
return mBookList;
}
@Override
public void addBook(Book book) throws RemoteException {
mBookList.add(book);
}
@Override
public void registerListener(IOnNewBookArrivedListener listener) throws RemoteException {
// if (!mListenerList.contains(listener)) {
// mListenerList.add(listener);
// } else {
// Log.e(TAG, "listener already exists.");
// }
// Log.e(TAG, "registerListener, size:" + mListenerList.size());
mListenerList.register(listener);
}
@Override
public void unregisterListener(IOnNewBookArrivedListener listener) throws RemoteException {
// if (mListenerList.contains(listener)) {
// mListenerList.remove(listener);
// Log.e(TAG, "unregister listener succeed.");
// } else {
// Log.e(TAG, "not found, can not unregister.");
// }
//
// Log.e(TAG, "unregisterListener, current size:" + mListenerList.size());
mListenerList.unregister(listener);
}
}
package com.example.binderpool.aidl;
import android.os.RemoteException;
public class AuthImpl extends IAuth.Stub {
@Override
public User getCurrentUser() throws RemoteException {
User user = new User(1, "ZOUJIN", "ZOUJIN6649", "https://dss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=2075772401,2375569036&fm=179&app=42&f=JPEG?w=121&h=140&s=D7F5C46A051445C018C03E68030090F5");
return user;
}
}
下面为Binder连接池创建AIDL接口IBinderPool.aidl
// IBinderPool.aidl
package com.example.binderpool.aidl;
// Declare any non-default types here with import statements
interface IBinderPool {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
IBinder queryBinder(int binderCode);
}
接下来我们为Binder连接池创建远程Service并实现IBinderPool
public class BinderPool {
private static final String TAG = "BinderPool";
public static final int BINDER_NONE = -1;
public static final int BINDER_BOOK_MANAGER = 0;
public static final int BINDER_AUTH = 1;
private Context mContext;
private IBinderPool mBinderPool;
private static volatile BinderPool sInstance;
private CountDownLatch mConnectionBinderPoolCountDownLatch;
private ServiceConnection mBinderPoolConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mBinderPool = IBinderPool.Stub.asInterface(iBinder);
// try {
// mBinderPool.asBinder().linkToDeath(mBinderPoolDeathRecipient, 0);
// } catch (RemoteException e) {
// e.printStackTrace();
// }
//将count值减1
mConnectionBinderPoolCountDownLatch.countDown();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mBinderPool = null;
connectionBinderPoolService();
}
};
// private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
// @Override
// public void binderDied() {
// Log.e(TAG, "binder died.");
// mBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient, 0);
// mBinderPool = null;
// connectionBinderPoolService();
// }
// };
private BinderPool(Context context) {
mContext = context.getApplicationContext();
connectionBinderPoolService();
}
public static BinderPool getInstance(Context context) {
if (sInstance == null) {
synchronized (BinderPool.class) {
if (sInstance == null) {
sInstance = new BinderPool(context);
}
}
}
return sInstance;
}
public synchronized void connectionBinderPoolService() {
mConnectionBinderPoolCountDownLatch = new CountDownLatch(1);
Intent service = new Intent(mContext, BinderPoolService.class);
mContext.bindService(service, mBinderPoolConnection, Context.BIND_AUTO_CREATE);
try {
//线程会挂起,直到count值为0才继续执行
mConnectionBinderPoolCountDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public IBinder queryBinder(int binderCode) {
IBinder binder = null;
try {
if (mBinderPool != null) {
binder = mBinderPool.queryBinder(binderCode);
}
} catch (RemoteException e) {
e.printStackTrace();
}
return binder;
}
public static class BinderPoolImpl extends IBinderPool.Stub {
@Override
public IBinder queryBinder(int binderCode) throws RemoteException {
IBinder binder = null;
switch (binderCode) {
case BINDER_BOOK_MANAGER:
binder = new BookManagerImpl();
break;
case BINDER_AUTH:
binder = new AuthImpl();
break;
default:
break;
}
return binder;
}
}
}
我们在BinderPool内部绑定远程服务,绑定成功后,客户端就可以通过queryBinder方法去获取各自对应的Binder,拿到所需的Binder后,不同业务模块就可以进行各自的操作了。接下来我们看一下服务端的Service
public class BinderPoolService extends Service {
private static final String TAG = "BinderPoolService";
private Binder mBinderPool = new BinderPool.BinderPoolImpl();
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "onCreate");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind");
return mBinderPool;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy");
}
}
最后我们验证一下效果
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "BinderPoolActivity";
Button getUserInfo;
Button getBookList;
ImageView headPic;
TextView userName;
TextView nickName;
TextView bookListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getUserInfo = findViewById(R.id.btn_get_user_info);
getBookList = findViewById(R.id.btn_get_book_list);
headPic = findViewById(R.id.headPic);
userName = findViewById(R.id.username);
nickName = findViewById(R.id.nickname);
bookListView = findViewById(R.id.bookList);
getUserInfo.setOnClickListener(this);
getBookList.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_get_user_info:
getUserInfo();
break;
case R.id.btn_get_book_list:
getBookList();
break;
}
}
private void getBookList() {
new Thread(new Runnable() {
@Override
public void run() {
BinderPool binderPool = BinderPool.getInstance(getApplicationContext());
IBinder bookManagerBinder = binderPool.queryBinder(BinderPool.BINDER_BOOK_MANAGER);
IBookManager bookManager = BookManagerImpl.asInterface(bookManagerBinder);
Log.e(TAG, "visit IBookManager");
Book book1 = new Book(1, "Android");
try {
bookManager.addBook(book1);
Log.e(TAG, "add book:" + book1.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
try {
final List<Book> bookList = bookManager.getBookList();
Log.e(TAG, "get book list:" + bookList.toString());
runOnUiThread(new Runnable() {
@Override
public void run() {
bookListView.setVisibility(View.VISIBLE);
bookListView.setText(bookList.toString());
}
});
} catch (RemoteException e) {
e.printStackTrace();
}
}
}).start();
}
private void getUserInfo() {
Log.e(TAG, "打印-->getUserInfo()");
new Thread(new Runnable() {
@Override
public void run() {
BinderPool binderPool = BinderPool.getInstance(getApplicationContext());
IBinder authBinder = binderPool.queryBinder(BinderPool.BINDER_AUTH);
IAuth auth = AuthImpl.asInterface(authBinder);
Log.e(TAG, "visit IAuth");
try {
final User user = auth.getCurrentUser();
Log.e(TAG, "get user info:" + user.toString());
runOnUiThread(new Runnable() {
@Override
public void run() {
userName.setText(user.getUserName());
nickName.setText(user.getNickName());
Glide.with(MainActivity.this).load(user.getHeadPic()).into(headPic);
}
});
} catch (RemoteException e) {
e.printStackTrace();
}
}
}).start();
}
}
效果如下: