Android IPC之Binder连接池(Android开发艺术探索随笔)

为什么要用Binder连接池?
当项目很大需要很多AIDL的时候,就需要建立很多Service,这是后系统看起来就会很庞大。这和时候我们就需要减少Service的数量,将所有AIDL放在一个service中去管理。
Binder连接池的工作机制是什么?
每个业务模块创建自己的AIDL接口并实现此接口,这个时候不同业务模块之间是不能有耦合的。所有实现细节我们要单独开来,然后向服务端提供自己的唯一标示和其对应的Binder对象,对于服务端来说,值需要一个Service就可以了,服务端提供一个queryBinder接口,这个接口可以根据业务模块的特征来返回响应的Binder对象给他们。

以书中的例子为例:
我们需要2个AIDL文件。

// ISecurityCenter.aidl
package com.gl.android_yishu;

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

interface ISecurityCenter {
    String encrypt(String content);
    String decrypt(String password);
}
// ICompute.aidl
package com.gl.android_yishu;

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

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

2个AIDL对应的实现类

public class ISecurityCenterImpl 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);
    }
}
public class ComputeImpl extends ICompute.Stub {
    @Override
    public int add(int a, int b) throws RemoteException {
        return a+b;
    }
}

BinderPool类

public class BinderPool {

    private static final String TAG = "BinderPool";
    public static final int BINDER_NONR = -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 mConnectBinderPoolCountDownLatch;

    private BinderPool(Context context){
        mContext = context;
        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() {
        mConnectBinderPoolCountDownLatch = new CountDownLatch(1);
        Intent service = new Intent(mContext,BinderPoolService.class);
        mContext.bindService(service,connection,Context.BIND_AUTO_CREATE);
        try {
            mConnectBinderPoolCountDownLatch.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;
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBinderPool = IBinderPool.Stub.asInterface(service);
            mConnectBinderPoolCountDownLatch.countDown();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    public static class BinderPoolImpl extends IBinderPool.Stub{

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

上面这个类实现了IBinderPool.AIDL。对应的AIDL文件

interface IBinderPool {
    IBinder queryBinder(int binderCode);
}

我们在客户端调用的时候,queryBinder()方法的时候,就会调起IBinderPool的queryBinder()方法,也就是BinderPoolImpl的queryBinder()方法,最后会返回对应code的binder对象。

binderPool = BinderPool.getInstance(MainActivity.this);
                        IBinder securityBinder = binderPool.queryBinder(BinderPool.BINDER_SECURITY_CENTER);

接着我们把这个Binder对象转化为对应的AIDL接口

ISecurityCenter mBinder = ISecurityCenterImpl.asInterface(securityBinder);

之后我们就可以调用AIDL接口的方法了。

String password = mBinder.encrypt("123");
                            Log.e("tag","this is encrypt ->"+password);

好,Binder连接池就到这里了。

你可能感兴趣的:(android,ipc,binder连接池)