1. 程式人生 > >Android IPC程序間通訊(七) Binder連線池

Android IPC程序間通訊(七) Binder連線池

Binder管家之Binder連線池

IPC程序間通訊(四)之AIDL中的AIDL由一個Service進行管理,若是建立10個AIDL業務模組是不是也要建立10個Service來進行管理,那100個呢?顯然繁瑣,怎麼辦麼,用Binder連線池呀!
工作機制:
1.每個業務模組建立其AIDL介面並實現此介面生成具有唯一標識的Binder。
2.Binder連線池將每個業務模組的Binder統一轉發給遠端Service。
3.遠端Service只需建立一個,並提供一個queryBinder介面,此介面根據業務模組的標識來返回相應的Binder給客戶端,客戶端即可進行遠端方法呼叫。
一,建立業務模組AIDL

package com.example.binderpooltest;
//加法功能
interface IPlus {
    int plus(int a,int b);
}
package com.example.binderpooltest;
//乘法功能
interface IMultiply {
    int multiply(int a,int b);
}

建立一個連線池的AIDL介面queryBinder用於根據業務模組的標識來返回相應的Binder給請求者

package com.example.binderpooltest;

//連線池依binderCode查詢Binder的介面
interface IBinderPool { IBinder queryBinder(int binderCode); }

二,建立子類繼承自己的AIDL生成Binder
命名規則 xxImple
先make project 一下生成AIDL對應的 xxx.java檔案
路徑\app\build\generated\source\aidl\debug\包名\xxx.java

package com.example.binderpooltest;
import android.os.RemoteException;

/**
 * 實現AIDL業務模組的Binder
 * IPlus為自定義AIDL生成的java類
 * public static abstract class Stub extends android.os.Binder implements com.example.binderpooltest.IPlus
 * Stub繼承自Binder所以IPlus.Stub即為Binder
 * 所以IPlusImple也是一個Binder
 */
public class IPlusImple extends IPlus.Stub { @Override public int plus(int a, int b) throws RemoteException { return a + b; } }
package com.example.binderpooltest;
import android.os.RemoteException;

public class IMultiplyImple extends IMultiply.Stub {

    @Override
    public int multiply(int a, int b) throws RemoteException {
        return a * b;
    }
}

三,建立BinderPool類作為連線池
知識點:
1.雙鎖實現單例項
2.共享鎖CountDownLatch實現同步
3.IBinder.DeathRecipient實現服務斷開重連

public class BinderPool {

    private static final String TAG = "DEBUG-WCL: " + BinderPool.class.getSimpleName();

    public static final int BINDER_CODE_ONE = 0;
    public static final int BINDER_CODE_TWO = 1;

    //自定義ADIL生成的IBinderPool.java類
    private IBinderPool mBinderPool;
    //第一鎖volatile全域性可見
    private static volatile BinderPool sInstance;
    private Context mContext;
    // 同步機制
    private CountDownLatch mCountDownLatch;

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

    // 單例
    public static BinderPool getInstance(Context context) {
        if (sInstance == null) {
            //第二鎖synchronized
            synchronized (BinderPool.class) {
                if (sInstance == null) {
                    sInstance = new BinderPool(context);
                }
            }
        }
        return sInstance;
    }

    // Binder的服務連線
    private ServiceConnection mBinderPoolConnection = new ServiceConnection() {
        @Override public void onServiceConnected(ComponentName name, IBinder service) {
            //以服務返回的IBinderPoolImple-Binder生成IBinderPool物件
            mBinderPool = IBinderPool.Stub.asInterface(service);
            try {
                mBinderPool.asBinder().linkToDeath(mDeathRecipient, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            //設定次數減一,此時為零,下一個開始連線
            mCountDownLatch.countDown();
        }

        @Override public void onServiceDisconnected(ComponentName name) {

        }
    };

    // 繫結服務池
    private synchronized void connectBinderPoolService() {
        //排隊連線,設定呼叫一次countDown()後,前一個連線斷開,後一個開始連線
        mCountDownLatch = new CountDownLatch(1);
        Intent service = new Intent(mContext, BinderService.class);
        mContext.bindService(service, mBinderPoolConnection, Context.BIND_AUTO_CREATE);
        try {
            //其餘等待
            mCountDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 失效重聯機制, 當Binder死亡時, 重新連線
    private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
        @Override public void binderDied() {
            Log.d(TAG, "Binder失效");
            mBinderPool.asBinder().unlinkToDeath(mDeathRecipient, 0);
            mBinderPool = null;
            connectBinderPoolService();
        }
    };


    /**
     * 用於被客戶端呼叫,請求Binder  ,最終為向服務端請求
     * 此時的mBinderPool為連結服務時從服務返回的IBinderPoolImple-Binder生成的IBinderPool介面
     * 即可呼叫介面方法queryBinder(binderCode)即回掉到IBinderPoolImple.queryBinder(int binderCode)
     * @param binderCode binder程式碼
     * @return Binder
     */
    public IBinder queryForBinder(int binderCode) {
        IBinder binder = null;
        try {
            if (mBinderPool != null) {
                binder = mBinderPool.queryBinder(binderCode);
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return binder;
    }

    /**
     * 用於被服務端呼叫,執行與服務端,當客戶端向BinderPool發起Binder請求,BinderPool向服務請求,返回Binder給客戶端
     * public static abstract class Stub extends android.os.Binder implements com.example.binderpooltest.IBinderPool
     * IBinderPool.Stub實現了AIDL介面IBinderPool
     * IBinderPoolImple繼承IBinderPool.Stub,所以IBinderPoolImple重寫了AIDL介面方法,若其他地方呼叫
     * IBinderPool.queryBinder(binderCode)即會回撥到此方法
     */
    public static class IBinderPoolImple extends IBinderPool.Stub {

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

            IBinder iBinder = null;
            switch (binderCode) {
                case BINDER_CODE_ONE:
                    iBinder = new IPlusImple();
                    break;
                case BINDER_CODE_TWO:
                    iBinder = new IMultiplyImple();
                    break;
            }
            return iBinder;
        }
    }
}

四,建立服務用於管理BinderPool傳送過來的Binder

public class BinderService extends Service {

    public BinderService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }
	//呼叫BinderPool中的,AIDL查詢介面queryBinder的實現類,其中實現了依binderCode返回Binder的方法
	//將此IBinder返回給BinderPool
    private IBinder mBinder = new BinderPool.IBinderPoolImple();

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

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

五,前臺客戶端實現

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    //請求Binder的唯一標識
    public static final int METHOD_CODE_ONE = 1;
    public static final int METHOD_CODE_TWO = 2;
    private Context mContext;
    private BinderPool mBinderPool;
    //請求並希望返回的IBinder
    private IBinder mPlusBinder;
    private IBinder mMultuplyBinder;
    //以返回的IBinder建立的介面
    private IPlus mIPlus;
    private IMultiply mIMultiply;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = getApplicationContext();
        new Thread(new doWork()).start();
    }

    private class doWork implements Runnable {
        public doWork() {
            super();
        }

        @Override
        public void run() {
            int a = 2;
            int b = 5;
            Log.d(TAG, "doWork: 1");
            //建立BinderPool單例項
            mBinderPool = BinderPool.getInstance(mContext);
            Log.d(TAG, "doWork: 2");
            try {
                //請求的IBinder
                mPlusBinder = mBinderPool.queryForBinder(METHOD_CODE_ONE);
                Log.d(TAG, "doWork: 3");
                //以返回的IBinder建立介面
                mIPlus = IPlusImple.asInterface(mPlusBinder);
                //呼叫遠端方法
                int result1 = mIPlus.plus(a, b);
                mMultuplyBinder = mBinderPool.queryForBinder(METHOD_CODE_TWO);
                mIMultiply = IMultiplyImple.asInterface(mMultuplyBinder);
                int result2 = mIMultiply.multiply(a, b);
                Toast.makeText(mContext, "a + b = " + result1 + "/n" +
                        "a × b = " + result2, Toast.LENGTH_SHORT).show();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
}