AIDL使用およびBinder接続プール


1.AIDL使用
Demo詳細アドレス
AIDLはAndroid特有のプロセス間通信手段であり、AIDLの使用を見た後、現在流行しているRPCフレームワークと似ているような気がします.RPCもインタフェース定義言語を使用してインタフェースオブジェクトとインタフェース定義を宣言する必要がある.対応するリモートコールコードを生成します.
プロセスAが2つのサービスを提供するシーンがあるとします.
a.図書リストの照会
b.図書の追加
    1. まず、このブックのオブジェクトを2つのプロセス前に渡す必要があるため、Android特有のシーケンス化インタフェースParcelableを実現する必要がある図書クラスを宣言する必要があります.
package com.alipay.aidl.test;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by tianbei on 2016/1/31.
 */
public class Book implements Parcelable {

    public int bookId;

    public String bookName;

    public Book(int bookId, String bookName) {
        this.bookId = bookId;
        this.bookName = bookName;
    }

    public Book(Parcel in) {
        bookId = in.readInt();
        bookName = in.readString();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(bookId);
        dest.writeString(bookName);
    }

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {

        @Override
        public Book createFromParcel(Parcel source) {
            return new Book(source);
        }

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }

    };
}

    2. aidlファイルの定義
aidlインタフェースで使用するカスタムクラスについては、aidlファイルで宣言する必要があります.次はブックです.aidl.
package com.alipay.aidl.test;

parcelable Book;

図書管理インタフェースaidlファイル
// IBookManager.aidl
package com.alipay.aidl.test;

import com.alipay.aidl.test.Book;
import com.alipay.aidl.test.IOnNewBookArrivedListener;

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

interface IBookManager {

    List getBookList();

    void addBook(in Book book);

    void registerListener(in IOnNewBookArrivedListener listener);

    void unregisterListener(in IOnNewBookArrivedListener listener);

}
図書購読メッセージプッシュインタフェース:
// IOnNewBookArrivedListener.aidl
package com.alipay.aidl.test;
import com.alipay.aidl.test.Book;

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

interface IOnNewBookArrivedListener {

    void onNewBookArrived(in Book book);

}
 
上記のコードは、クライアント・プロセスとサービス・エンド・プロセスの両方に存在する必要があります.クライアントとサービス側はIBookManagerインタフェースとBookクラスを使用する必要があるためです.
サービス側コードはIBookManagerを実現する必要がある.Stubインタフェースは、特定のビジネスロジックを実行します.たとえば、図書の追加:サービス側は図書を保存する必要があり、データベースの永続化に保存することができます.これがサービス側のビジネスロジックです.具体的なビジネスロジックを実現する前に、Android studioが生成したインタフェースファイルIBookManagerを見てみましょう.java.このJavaクラスは複雑に見えますが、構造は簡単で、クラスIinterfaceを継承しています.
a.インタフェースメソッド定義、例えばaidlファイルで宣言したaddBookメソッド、getBookListメソッド.
b.内部クラスStub.このクラスにはIBinderが統合されています.これは、サービス側で実行されるBinderクラスです.サービス側コードは、このクラスを統合することによって、具体的なビジネスロジックを行います.
c.Proxyクラス:クライアントで実行され、http通信時の論理と同様に、インパラメトリックシーケンス化され、リモートコールされ、返される結果が逆シーケンス化されます.
次に、サービス側のコードを見てみましょう.
package com.alipay.aidl.test;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Created by tianbei on 2016/1/31.
 */
public class BookManagerService extends Service {

    private static final String TAG = "BMS";

    private List mBookList = new CopyOnWriteArrayList();

    private RemoteCallbackList mListenerList =
            new RemoteCallbackList();

    private Binder mBinder = new IBookManager.Stub(){

        @Override
        public List getBookList() throws RemoteException {
            return mBookList;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
            onNewBookArrived(book);
        }

        @Override
        public void registerListener(IOnNewBookArrivedListener listener) throws RemoteException {
            mListenerList.beginBroadcast();
            boolean result = mListenerList.register(listener);
            Log.d(TAG, "register listener :" + result);
            mListenerList.finishBroadcast();
        }

        @Override
        public void unregisterListener(IOnNewBookArrivedListener listener) throws RemoteException {
            mListenerList.beginBroadcast();
            boolean result = mListenerList.unregister(listener);
            Log.d(TAG, "unregister listener :" + result);
            mListenerList.finishBroadcast();
        }
    };

    public void onNewBookArrived(Book book) {
        mBookList.add(book);
        int N = mListenerList.beginBroadcast();
        for(int i = 0; i < N; i++) {
            IOnNewBookArrivedListener listener = mListenerList.getBroadcastItem(i);
            try {
                listener.onNewBookArrived(book);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        mListenerList.finishBroadcast();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mBookList.add(new Book(1, "ARM       "));
        mBookList.add(new Book(2, "Android      "));
    }

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

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

BookManagerServiceはサービス側で動作するサービスクラスで、内部匿名クラスがあり、IBookManagerを実現しています.Stubインタフェースです.これは、aidlインタフェース定義ファイルで宣言された4つの方法を実装するサービス側で実行されるコードです.図書の追加、図書リストの取得、図書の追加時に、マネージャーに登録されている各listenerを呼び出して、他のプロセスに新しい本が掲載されていることを通知します.
2.Binder接続プール
なぜBinderスレッドプールが必要なのでしょうか?上記のように、サーバ側プロセスは、クライアントプロセスが呼び出すためにBinderインタフェースを宣言するたびに、サービスコンポーネントを宣言する必要があります.一方、クライアント側に100個のBinderクラスがある場合は、100個のServiceコンポーネントを定義し、Manifestファイルで宣言する必要があります.これはシステムリソースを消費します.
上記の実装では、サービス側がBinderクラスをクライアントに返す方法は、onBindの実装でIBookManagerを返すことであることがわかる.Stubオブジェクト.
では、統合されたサービスを定義し、クライアント・プロセスから識別情報を送信し、サービス側プロセスは異なる識別情報を通じて異なるBinderオブジェクトを返すことができますか?答えはいいです.
ここでは詳しくは言わないで、直接デモに行きます.Demo詳細アドレス