您的位置:首页 > 移动开发 > Android开发

Android跨进程通信之Binder连接池及选择合适的IPC方式

2018-01-30 00:15 489 查看
借鉴自开发艺术

AIDL是最常用的多进程通信的技术,但是每次使用都要创建一个Service,开销太大,应该把所有的AIDL都放到一个Service里。

每个业务模块都创建自己的AIDL接口并实现,业务模块间不能有耦合,然后向服务器提供自己的唯一标识和对应的Binder对象。对于服务端,1个Service足够了。服务端提供一个queryBinder接口,从中可以获取业务模块对应的Binder。拿到Binder就可以远程调用了。所以,Binder连接池的作用是把所有业务模块的Binder请求统一转发到远程Service中去执行。

原理图



两个AIDL接口及其实现类

// ISecurityCenter.aidl
package com.example.test;

// Declare any non-default types here with import statements

interface ISecurityCenter {
String encrypt(String content);
String decrypt(String password);
}


// ICompute.aidl
package com.example.test;

// Declare any non-default types here with import statements

interface ICompute {
int add(int a, int b);
}


public class ComputeImpl extends ICompute.Stub {
@Override
public int add(int a, int b) throws RemoteException {
return a + b;
}
}


public class SecurityCenterImpl extends ISecurityCenter.Stub {

private static final char SECRET_CODE = '^';

@Override
public String encrypt(String content) throws RemoteException {
char[] chars = content.toCharArray();
for (int i = 0; i < chars.length; i ++) {
chars[i] ^= SECRET_CODE;
}
return new String(chars);
}

@Override
public String decrypt(String password) throws RemoteException {
return encrypt(password);
}
}


一个Binder池接口

// IBinderPool.aidl
package com.example.test;

// Declare any non-default types here with import statements

interface IBinderPool {
IBinder queryBinder(int binderCode);
}


Binder池管理类,其实相当于工具类

public class BinderPool {
private static final String TAG = "BinderPool";
public static final int BINDER_NONE = -1;
public static final int BINDER_COMPUTE = 0;
public static final int BINDER_SECURITY_CENTER = 1;

private Context mContext;
private IBinderPool mBinderPool;
private static volatile BinderPool sInstance;
private CountDownLatch mConnectionBinderPoolCountDownLatch;

private BinderPool (Context context) {
mContext = context.getApplicationContext();
connectBinderPoolService();
}

public static BinderPool getInstance(Context context) {
if (sInstance == null) {
synchronized (BinderPool.class) {
if (sInstance == null) {
sInstance = new BinderPool(context);
}
}
}
return sInstance;
}

private synchronized void connectBinderPoolService() {
mConnectionBinderPoolCountDownLatch = new CountDownLatch(1);
Intent service = new Intent(mContext, BinderPoolService.class);
mContext.bindService(service, mBinderPoolConnection, Context.BIND_AUTO_CREATE);
try {
mConnectionBinderPoolCountDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public IBinder queryBinder(int binderCode) {
IBinder binder = null;
if (mBinderPool != null) {
try {
binder = mBinderPool.queryBinder(binderCode);
} catch (RemoteException e) {
e.printStackTrace();
}
}
return binder;
}

private ServiceConnection mBinderPoolConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinderPool = IBinderPool.Stub.asInterface(service);
try {
mBinderPool.asBinder().linkToDeath(mBinderPoolDeathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
}

@Override
public void onServiceDisconnected(ComponentName name) {
}
};

private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.w(TAG, "binderDied: ");
mBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient, 0);
mBinderPool = null;
connectBinderPoolService();
}
};

public static class BinderPoolImpl extends IBinderPool.Stub {
public BinderPoolImpl() {
super();
}

@Override
public IBinder queryBinder(int binderCode) throws RemoteException {
IBinder binder = null;
switch (binderCode) {
case BINDER_SECURITY_CENTER :
binder = new SecurityCenterImpl();
break;
case BINDER_COMPUTE :
binder = new ComputeImpl();
break;
}
return binder;
}
}
}


service

public class BinderPoolService extends Service {

private static final String TAG = "xbh";

private Binder mBinderPool = new BinderPool.BinderPoolImpl();

@Override
public void onCreate() {
super.onCreate();
}

public BinderPoolService() {
}

@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind: ");
return mBinderPool;
}

@Override
public void onDestroy() {
super.onDestroy();
}
}


调用

public class MainActivity extends AppCompatActivity {

private static final String TAG = "xbh";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
doWork();
}
}).start();
}

private void doWork() {
BinderPool binderPool = BinderPool.getInstance(this);
IBinder securityBinder = binderPool.queryBinder(BinderPool.BINDER_SECURITY_CENTER);
ISecurityCenter mSecurityCenter = SecurityCenterImpl.asInterface(securityBinder);
Log.i(TAG, "visit ISecurityCenter");
String msg = "helloworld-安卓";
Log.i(TAG, msg);
try {
String password = mSecurityCenter.encrypt(msg);
Log.i(TAG, password);
Log.i(TAG, mSecurityCenter.decrypt(password));
} catch (RemoteException e) {
e.printStackTrace();
}

Log.i(TAG, "visit ICompute");
IBinder computeBindedr = binderPool.queryBinder(BinderPool.BINDER_COMPUTE);
ICompute mCompute = ComputeImpl.asInterface(computeBindedr);
try {
Log.i(TAG, mCompute.add(3,5) + "");
} catch (RemoteException e) {
e.printStackTrace();
}
}
}


选择合适的IPC方式

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: