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()方法會阻塞程序繼續(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)系作者
  • 序言:七十年代末铐刘,一起剝皮案震驚了整個(gè)濱河市陪每,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖檩禾,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挂签,死亡現(xiàn)場離奇詭異,居然都是意外死亡盼产,警方通過查閱死者的電腦和手機(jī)饵婆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來戏售,“玉大人侨核,你說我怎么就攤上這事」嘣郑” “怎么了搓译?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長锋喜。 經(jīng)常有香客問我些己,道長,這世上最難降的妖魔是什么嘿般? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任段标,我火速辦了婚禮,結(jié)果婚禮上炉奴,老公的妹妹穿的比我還像新娘逼庞。我一直安慰自己,他們只是感情好盆佣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布往堡。 她就那樣靜靜地躺著,像睡著了一般共耍。 火紅的嫁衣襯著肌膚如雪虑灰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天痹兜,我揣著相機(jī)與錄音穆咐,去河邊找鬼。 笑死字旭,一個(gè)胖子當(dāng)著我的面吹牛对湃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播遗淳,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼拍柒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了屈暗?” 一聲冷哼從身側(cè)響起拆讯,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤脂男,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后种呐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宰翅,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年爽室,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了汁讼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡阔墩,死狀恐怖嘿架,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情戈擒,我是刑警寧澤眶明,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站筐高,受9級特大地震影響搜囱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜柑土,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一蜀肘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧稽屏,春花似錦扮宠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至薄腻,卻和暖如春收捣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背庵楷。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工罢艾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人尽纽。 一個(gè)月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓咐蚯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親弄贿。 傳聞我的和親對象是個(gè)殘疾皇子春锋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容

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