美文网首页
IPC机制(下)

IPC机制(下)

作者: 管弦_ | 来源:发表于2018-12-02 18:54 被阅读0次

目录

  • Binder线程池
  • 选用合适的IPC方式

Binder线程池

当项目业务庞大时,我们需要减少Service的数量,将所有的AIDL放在同一个Service中去管理。在这种模式下,整个工作机制是这样的:

每个业务模块创建自己的AIDL接口并实现此接口,这个时候不同业务模块之间是不能有耦合的,所有实现细节我们要单独开来,然后向服务端提供自己的唯一标识和其对应的Binder对象;

对于服务端来说,只需要一个Service就可以了,服务端提供一个queryBinder接口,这个接口能够根据业务模块的特征来返回相应的Binder对象给它们,不同的业务模块拿到所需的Binder对象后就可以进行远程方法调用了。

由此可见,Binder连接池的主要作用就是将每个业务模块的Binder请求统一转发到远程Service中去执行,从而避免了重复创建Service的过程,它的工作原理如图所示。

Binder连接池的工作原理

我们提供两个AIDL接口来模拟多个业务使用AIDL的情况。

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

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

完成这两个AIDL接口的实现。

public class SecurityCenterImpl extends ISecurityCenter.Stub {

    private static final char SECRTE_CODE = '^';

    @Override
    public String encrypt(String content) throws RemoteException {
        char[] chars = content.toCharArray();
        for(int i = 0; i < chars.length; i++){
            chars[i] ^= SECRTE_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;
    }
}

为Binder连接池创建AIDL接口。

interface IBinderPool {
    IBinder queryBinder(int binderCode);
}

为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();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinderPool;
    }

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

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 mConnectBinderPoolCountDownLatch;

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

    //单例模式,同一进程只会初始化一次
    public static BinderPool getsInstance(Context context){
        if(sInstance == null){
            synchronized (BinderPool.class){
                if(sInstance == null){
                    sInstance = new BinderPool(context);
                }
            }
        }
        return sInstance;
    }

    //连接远程服务Service
    private synchronized void connectBinderPoolService() {

        mConnectBinderPoolCountDownLatch = new CountDownLatch(1);
        Intent service = new Intent(mContext, BinderPoolService.class);
        mContext.bindService(service, mBinderPoolConnection, Context.BIND_AUTO_CREATE);
        try {
            //将异步操作转换成同步操作
            mConnectBinderPoolCountDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    //暴露给客户端使用的方法,底层通过IBinderPool实现,返回某个具体业务的binder对象
    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();
            }
            mConnectBinderPoolCountDownLatch.countDown();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void 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 {
            //通过binderCode返回某个具体业务的binder对象
            IBinder binder = null;
            switch (binderCode){
                case BINDER_SECURITY_CENTER:
                    binder = new SecurityCenterImpl();
                    break;
                case BINDER_COMPUTE:
                    binder = new ComputeImpl();
                    break;
                default:
                    break;
            }
            return binder;
        }
    }
}

客户端的实现。

public class BinderPoolActivity extends Activity {

    private static final String TAG = "BinderPoolActivity";

    private ISecurityCenter mSecurityCenter;
    private ICompute mCompute;

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

        //Binder方法的调用过程有可能是耗时的,所以需要在子线程中执行
        new Thread(new Runnable() {
            @Override
            public void run() {
                doWork();
            }
        }).start();

    }

    private void doWork() {
        //获取BinderPool线程池对象
        BinderPool binderPool = BinderPool.getsInstance(BinderPoolActivity.this);
        //通过BinderPool线程池queryBinder方法得到某个具体业务的IBinder对象
        IBinder securityBinder = binderPool.queryBinder(BinderPool.BINDER_SECURITY_CENTER);
        //通过IBinder对象实例化该具体业务接口
        mSecurityCenter = SecurityCenterImpl.asInterface(securityBinder);
        Log.d(TAG, "visit ISecurityCenter");
        String msg = "helloworld-安卓";
        System.out.println("content: "+ msg);

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

        Log.d(TAG, "visit ICompute");
        //通过BinderPool线程池queryBinder方法得到某个具体业务的IBinder对象
        IBinder computeBinder = binderPool.queryBinder(BinderPool.BINDER_COMPUTE);
        //通过IBinder对象实例化该具体业务接口
        mCompute = ComputeImpl.asInterface(computeBinder);
        try {
            System.out.println("3+5="+mCompute.add(3, 5));
        } catch (RemoteException e) {
            e.printStackTrace();
        }

    }
}

选用合适的IPC方式

IPC方式的优缺点和适用场景

参考资料:

《Android开发艺术探索》

Android开发艺术探索笔记

相关文章

网友评论

      本文标题:IPC机制(下)

      本文链接:https://www.haomeiwen.com/subject/ilcscqtx.html