2.5 Binder連接池

1. aidl實(shí)現(xiàn)流程概述

首先建立一個(gè)aidl接口和一個(gè)Service,接著實(shí)現(xiàn)一個(gè)類A繼承aidl接口中的Stub類并實(shí)現(xiàn)其中的方法,在Service綁定時(shí)返回類A的對象,然后客戶端就可以綁定服務(wù)端,建立連接后就可以訪問遠(yuǎn)程服務(wù)端的方法了。

2. 可能出現(xiàn)的問題及解決方式

公司項(xiàng)目越來越大,100個(gè)aidl,按照上面的思路,得100個(gè)Service。這顯然不可以,解決方式是binder 連接池。
整個(gè)工作機(jī)制是這樣的:每個(gè)業(yè)務(wù)模塊創(chuàng)建自己的aidl接口并實(shí)現(xiàn)此接口,這個(gè)時(shí)候不同業(yè)務(wù)模塊之間是不能有耦合的,然后向服務(wù)端提供自己的唯一標(biāo)識和其對應(yīng)的Binder對象;對于服務(wù)端來說,只需要一個(gè)Service,服務(wù)端提供一個(gè)queryBinder接口,這個(gè)接口能夠根據(jù)業(yè)務(wù)模塊特征來返回相應(yīng)的Binder對象給他們,不同的業(yè)務(wù)模塊拿到所需的Binder對象后就可以進(jìn)行遠(yuǎn)程方法調(diào)用了。
Binder連接池的主要作用就是將每個(gè)業(yè)務(wù)模塊的Binder請求同一轉(zhuǎn)發(fā)到遠(yuǎn)程Service中去,避免重復(fù)創(chuàng)建Service的過程。

3. 定義兩個(gè)業(yè)務(wù)aidl接口并實(shí)現(xiàn)

package qingfengmy.developmentofart._2activity.binderpool.aidl;

interface ICompute {
    int add(int a, int b);
}
// ISecurityCenter.aidl
package qingfengmy.developmentofart._2activity.binderpool.aidl;

interface ISecurityCenter {
    String encrypt(in String content);
    String decrypt(in String password);
}
public class SecurityCenterImpl extends ISecurityCenter.Stub {
    @Override
    public String encrypt(String content) throws RemoteException {
        char[] chars = content.toCharArray();
        for (int i=0; i<chars.length;i++) {
            chars[i] = (char) (chars[i]+1);
        }

        return new String(chars);
    }

    @Override
    public String decrypt(String password) throws RemoteException {
        char[] chars = password.toCharArray();
        for (int i=0; i<chars.length;i++) {
            chars[i] = (char) (chars[i]-1);
        }

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

4. 定義BinderPool接口并實(shí)現(xiàn)

package qingfengmy.developmentofart._2activity.binderpool.aidl;

interface IBinderPool {
    IBinder queryBinder(int binderCode);
}
public static class BinderPoolImpl extends IBinderPool.Stub{

    @Override
    public IBinder queryBinder(int binderCode) throws RemoteException {
        switch (binderCode) {
            case 0:
                return new SecurityCenterImpl();
            case 1:
                return new ComputerImpl();
        }
        return null;
    }
}

5. 服務(wù)實(shí)現(xiàn)

public class PoolService extends Service {
    private Binder mBinderPool = new BinderPool.BinderPoolImpl();

    public PoolService() {
    }

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

}

6. BinderPool的實(shí)現(xiàn)

public class BinderPool {

    // 定義BinderCode
    private 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;
    // volatile 用來修飾被不同線程訪問和修改的變量
    private static volatile BinderPool sInstance;
    /**
     * CountDownLatch類是一個(gè)同步計(jì)數(shù)器,構(gòu)造時(shí)傳入int參數(shù),該參數(shù)就是計(jì)數(shù)器的初始值,每調(diào)用一次countDown()方法,計(jì)數(shù)器減1,計(jì)數(shù)器大于0 時(shí),await()方法會(huì)阻塞程序繼續(xù)執(zhí)行
     * CountDownLatch如其所寫,是一個(gè)倒計(jì)數(shù)的鎖存器,當(dāng)計(jì)數(shù)減至0時(shí)觸發(fā)特定的事件。利用這種特性,可以讓主線程等待子線程的結(jié)束。
     */
    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;
    }

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

    private synchronized void connectBinderPoolService() {
        // 只有一個(gè)線程有效
        mConnectBinderPoolCountDownLatch = new CountDownLatch(1);
        Intent intent = new Intent(mContext, PoolService.class);
        mContext.bindService(intent, mBinderPoolConnection, Context.BIND_AUTO_CREATE);
        // 等待,直到CountDownLatch中的線程數(shù)為0
        mConnectBinderPoolCountDownLatch.await();
    }

    private ServiceConnection mBinderPoolConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBinderPool = IBinderPool.Stub.asInterface(service);
            mBinderPool.asBinder().linkToDeath(mBinderPoolDeathRecipient, 0);
            // 執(zhí)行一次countDown,其計(jì)數(shù)減一
            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 {

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

7. Activity中調(diào)用

private void doWork() {
    BinderPool binderPool = BinderPool.getsInstance(this);
    IBinder computeBinder = binderPool.queryBinder(BinderPool.BINDER_COMPUTE);
    ICompute compute = ComputerImpl.asInterface(computeBinder);
    try {
        int result = compute.add(1, 2);
        Log.e("aaa", "1+2=" + result);
    } catch (RemoteException e) {
        e.printStackTrace();
    }

    IBinder securityCenterBinder = binderPool.queryBinder(BinderPool.BINDER_SECURITY_CENTER);
    ISecurityCenter iSecurityCenter = SecurityCenterImpl.asInterface(securityCenterBinder);
    try {
        String content = "i love this book";
        Log.e("aaa","加密前:"+content);
        content = iSecurityCenter.encrypt(content);
        Log.e("aaa","加密后:"+content);
        content = iSecurityCenter.decrypt(content);
        Log.e("aaa","解密后:"+content);
    } catch (RemoteException e) {
        e.printStackTrace();
    }

}

普通寫法

public void onServiceConnected(ComponentName name, IBinder service) {
    iBookManager = IBookManager.Stub.asInterface(service);
}

可見使用BinderPool客戶端中的處理還是一樣,通過Stub的asInterface方法把IBinder轉(zhuǎn)為業(yè)務(wù)接口。
這樣有新業(yè)務(wù)aidl時(shí),只需加aidl_code,并在queryBinder中增加返回的aidl即可。不需寫Servicce,所以如果使用aidl,必須推薦使用BinderPool模式。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,539評論 19 139
  • Jianwei's blog 首頁 分類 關(guān)于 歸檔 標(biāo)簽 巧用Android多進(jìn)程,微信,微博等主流App都在用...
    justCode_閱讀 6,115評論 1 23
  • 毫不夸張地說,Binder是Android系統(tǒng)中最重要的特性之一;正如其名“粘合劑”所喻,它是系統(tǒng)間各個(gè)組件的橋梁...
    weishu閱讀 18,102評論 29 246
  • Android跨進(jìn)程通信IPC整體內(nèi)容如下 1、Android跨進(jìn)程通信IPC之1——Linux基礎(chǔ)2、Andro...
    隔壁老李頭閱讀 10,970評論 13 43
  • 我對天空說 你的深邃蒼茫 是我終日仰望的高處 我對大地說 你的廣袤無垠 是我踏之不遍的長度 我對大海說 你的幽暗無...
    明_熙閱讀 392評論 12 26

友情鏈接更多精彩內(nèi)容