Binder连接池

Binder连接池

首先回顾一下 AIDL 的 大致流程:首先创建一个Service和一个AIDL接口,接着创建一个类继承自AIDL接口中的Stub类并实现Stub中的抽象方法,在Service的onBind方法中返回这个类的对象,然后客户端就可以绑定Service,建立连接就可以访问远程服务端的方法了。

如果有100个地方需要用到 AIDL ,需要创建100个 Service 吗?

答案是显而易见的,这时我们需要将AIDL放在同一个Service中去管理。

在这种模式下,整个工作机制是这样的:每个业务模块创建自己的 AIDL 接口并实现此接口,这个时候不同业务模块之间是不能有耦合的,所有的实现细节需要单独开来,然后向服务端提供一个唯一标识和其对应的 Binder 对象; 对于服务端来说,只需要一个 Service 就可以了,服务端提供一个 queryBinder 接口,这个接口会返回相应的 Binder对象。Binder 连接池的主要作用就是将每个业务模块的 Binder 请求统一转发到远程 Service 中去执行,从而避免了重复创建Service工程。

下面看一个简单的例子

1.提供两个 AIDL 接口 :ISecurityCenter 和 ICompute

// ISecurityCenter.aidl

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

interface ICompute {

    int add(int a,int b);
}

2.实现这两个接口

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

3.为 Binder 连接池创建AIDL接口 IBinderPool.aidl

// IBinderPoll.aidl

interface IBinderPool {
   IBinder queryBinder(int binderCode);
}

4.为Binder连接池创建远程Service并实现IBinderPool

@Override
        public IBinder queryBinder(int binderCode) throws RemoteException {

            IBinder binder = null;
            switch (binderCode) {
                case BINDER_SECURITY_CENTER:
                    binder = new SecurityCenterIml();
                    break;
                case BINDER_COMPUTE:
                    binder = new ComputeIml();
                    break;
                default:
                    break;
            }

            return binder;
        }
    }

当Binder连接池连接上远程服务时,会根据不同模块的标识即binderCode返回不同的Binder对象,通过这个Binder对象所执行的操作全部发生在远程服务端。

5.Service 的实现比较简单

public class BinderPoolService extends Service {

    private static final String TAG = "BinderPoolService";

    private Binder mBinderPool = new BinderPool.BinderPoolImpl();

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

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

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

}

6.Binder连接池内部需要去绑定远程服务,绑定成功后服务端就可以通过它的queryBinder方法去获取对应的Binder。

public class BinderPool {

    public static final int BINDER_SECURITY_CENTER = 1;
    public static final int BINDER_NONE = -1;
    public static final int BINDER_COMPUTE = 0;

    private Context mContext;


    private IBinderPool mBinderPool;
    private static volatile BinderPool sInstance;
    private CountDownLatch mConnectBinderPoolCountDownLatch;
    private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            mBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient,0);
            mBinderPool = null;
            connectBinderPoolService();
        }
    };
    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();
            }

            mConnectBinderPoolCountDownLatch.countDown();

        }

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

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

    }

    private synchronized void connectBinderPoolService() {
        mConnectBinderPoolCountDownLatch = new CountDownLatch(1);
        Intent intent = new Intent(mContext,BinderPoolService.class);
        mContext.bindService(intent,mBinderPoolConnection,Context.BIND_AUTO_CREATE);

        try {
            mConnectBinderPoolCountDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public IBinder queryBinder(int bindService){
        IBinder binder = null;

        if (mBinderPool != null){
            try {
                binder = mBinderPool.queryBinder(bindService);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        return binder;
    }

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



    public static class BinderPoolIml extends IBinderPool.Stub {


        @Override
        public IBinder queryBinder(int binderCode) throws RemoteException {

            IBinder binder = null;
            switch (binderCode) {
                case BINDER_SECURITY_CENTER:
                    binder = new SecurityCenterIml();
                    break;
                case BINDER_COMPUTE:
                    binder = new ComputeIml();
                    break;
                default:
                    break;
            }

            return binder;
        }
    }
}

7.客户端代码

public class BinderPoolActivity extends AppCompatActivity {

    private ISecurityCenter mSecurityCenter;
    private ICompute mCompute;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_binder_pool);

        new Thread(new Runnable() {
            @Override
            public void run() {
                doWork();
            }
        }).start();
    }

    private void doWork() {
        BinderPool binderPool = BinderPool.getsInstance(BinderPoolActivity.this);
        IBinder securityBinder = binderPool.queryBinder(BinderPool.BINDER_SECURITY_CENTER);

        mSecurityCenter = SecurityCenterIml.asInterface(securityBinder);

        String msg = "Hello 安卓";

        try {
            String password = mSecurityCenter.encrypt(msg);
            Logger.i("encrypt:" + password);
            Logger.i("decrypt:" + mSecurityCenter.decrypt(password));
        } catch (RemoteException e) {
            e.printStackTrace();
        }

        IBinder computeBinder = binderPool.queryBinder(BinderPool.BINDER_COMPUTE);
        mCompute = ComputeIml.asInterface(computeBinder);

        try {
            Logger.i("add 3 + 5 :" +  mCompute.add(3, 5) + "");
        } catch (RemoteException e) {
            e.printStackTrace();
        }

    }
}

Log

 ╔════════════════════════════════════════════════════════════════════════════════════════
 ║ Thread: Thread-245
 ╟────────────────────────────────────────────────────────────────────────────────────────
 ║ BinderPoolActivity.access$000  (BinderPoolActivity.java:11)
 ║    BinderPoolActivity.doWork  (BinderPoolActivity.java:39)
 ╟────────────────────────────────────────────────────────────────────────────────────────
 ║ encrypt:;221~寗匍
 ╚════════════════════════════════════════════════════════════════════════════════════════
 ╔════════════════════════════════════════════════════════════════════════════════════════
 ║ Thread: Thread-245
 ╟────────────────────────────────────────────────────────────────────────────────────────
 ║ 
 ║    BinderPoolActivity.doWork  (BinderPoolActivity.java:40)
 ╟────────────────────────────────────────────────────────────────────────────────────────
 ║ decrypt:Hello 安卓
 ╚════════════════════════════════════════════════════════════════════════════════════════ ╔════════════════════════════════════════════════════════════════════════════════════════
║ Thread: Thread-245
╟────────────────────────────────────────────────────────────────────────────────────────
║ BinderPoolActivity.access$000  (BinderPoolActivity.java:11)
║    BinderPoolActivity.doWork  (BinderPoolActivity.java:49)
╟────────────────────────────────────────────────────────────────────────────────────────
║ add 3 + 5 :8
╚════════════════════════════════════════════════════════════════════════════════════════

这样如果有新业务需要加新的 AIDL ,那么实现它自己的 AIDL 接口后,只需要修改 BinderPoolIml 中的 queryBinder 方法,给自己添加一个新的 binderCode 并返回对应的 Binder 对象即可。

另一张表格来说明如何选择合适的 IPC 方式

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值