Binder连接池

demo下载地址,此demo由两个module来区分Service和Client

  • AIDL流程:先创建一个Service和一个AIDL接口,接着创建一个类继承自AIDL接口中的Stub类并实现Stub 中的抽象方法,在Service的onBind方法中返回这个类的对象,然后客户端就可以绑定服务 端Service,建立连接后就可以访问远程服务端的方法了。
  • 上述是典型的AIDL使用流程,假设业务需要100个模块需要使用AIDL进行通信,为了避免创建100个Service占用资源且项目变得重量级,将所有的AIDL用一个Service去管理是必要的,从而学习Binder连接池就有必要了。
  • 整个工作机制是这样的:每个业务模块创建自己的AIDL接口并实现 此接口,这个时候不同业务模块之间是不能有耦合的,所有实现细节我们要单独开来,然 后向服务端提供自己的唯一标识和其对应的Binder对象;对于服务端来说,只需要一个 Service就可以了,服务端提供一个queryBinder接口,这个接口能够根据业务模块的特征来 返回相应的Binder对象给它们,不同的业务模块拿到所需的Binder对象后就可以进行远程 方法调用了。由此可见,Binder连接池的主要作用就是将每个业务模块的Binder请求统一 转发到远程Service中去执行,从而避免了重复创建Service的过程。

在这里插入图片描述

  • 下面对Binder连接池进行一个小的例子
  • 首先创建两个AIDL业务接口,根据AIDL原理,服务端和客户端都需要创建
// ISecurityCenter.aidl
package com.demo.aidlservice;

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

interface ISecurityCenter {

    String encrypt(String content);

    String decrypt(String password);

}

// ICompute.aidl
package com.demo.aidlservice;

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

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

然后创建IBinderPool.aidl提供查询具体Binder接口

// IBinderPool.aidl
package com.demo.aidlservice;

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

interface IBinderPool {
    IBinder queryBinder(int binderCode);
}

然后在Service端去实现接口

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++) {
            System.out.print("chars = " + chars[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;
    }
}

public class BinderPoolImpl extends IBinderPool.Stub {
    private static final String TAG = "Service BinderPoolImpl";

    public BinderPoolImpl() {
        super();
    }

    @Override
    public IBinder queryBinder(int binderCode) throws RemoteException {
        Log.e(TAG, "binderCode = " + binderCode);
        IBinder binder = null;
        switch (binderCode) {
            case 0:
                binder = new SecurityCenterImpl();
                break;
            case 1:
                binder = new ComputeImpl();
                break;
            default:
                break;
        }
        return binder;
    }
}

  • 最后服务端要做的就是创建Service然后在manifests配置Service,绑定Service的时候返回IBinderPool的实现,客户端通过queryBinder方法去区分具体的IBinder对象
public class BinderPoolService extends Service {
    private static final String TAG = "BinderPoolService";
    private Binder mBinderPool = new BinderPoolImpl();

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

}

  • 接下来是Client的代码,客户端除了需要根据AIDL原理需要和服务端一样的AIDL接口意外,还需要BinderPool来queryBinder获取Service服务。

public class BinderPool {
    private static final String TAG = "BinderPool";
    private Context mContext;
    private IBinderPool mBinderPool;
    private static volatile BinderPool sInstance;


    public BinderPool(Context context) {
        this.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() {
        Intent service = new Intent();
        service.setComponent(new ComponentName("com.demo.aidlservice", "com.demo.aidlservice.BinderPoolService"));
        mContext.bindService(service, mBinderPoolConnection, Context.BIND_AUTO_CREATE);
    }

    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 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.e(TAG, "binderDied");
            mBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient, 0);
            mBinderPool = null;
            connectBinderPoolService();
        }
    };

}

然后在Client中MainActivity中调用,我这里写了两个按钮点击分别获取不同的服务


public class MainActivity extends AppCompatActivity {
    private static final String TAG = "Client MainActivity";

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

    }

    public void enc(View view) {
        new Thread() {
            @Override
            public void run() {
                BinderPool iBinderPool = BinderPool.getInstance(MainActivity.this);
                try {
                    IBinder securityBinder = iBinderPool.queryBinder(0);
                    ISecurityCenter securityCenter = ISecurityCenter.Stub.asInterface(securityBinder);
                    String enc = securityCenter.encrypt("abc");
                    Log.e(TAG, "enc = " + enc);
                    String dec = securityCenter.decrypt("123");
                    Log.e(TAG, "dec = " + dec);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    public void add(View view) {
        new Thread() {
            @Override
            public void run() {
                BinderPool binderPool = BinderPool.getInstance(MainActivity.this);
                try {
                    IBinder iBinder = binderPool.queryBinder(1);
                    ICompute iCompute = ICompute.Stub.asInterface(iBinder);
                    int sum = iCompute.add(1, 2);
                    Log.e(TAG, "sum = " + sum);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }
}
  • 以上就是Binder连接池的用法,如果增加服务端AIDL业务需求,只需修改服务端的BinderPoolImpl和新增对应的AIDL接口就可以了,BinderPool能够极大地提高AIDL的开 发效率,并且可以避免大量的Service创建,因此,建议在AIDL开发工作中引入BinderPool 机制。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值