Service
インターフェイスを使用してリモートプロセスでと通信するアプリケーションがありMessenger
ます。設定方法の基本的なアーキテクチャは次のとおりです。
- アプリケーションは、サービスへのアクセスを必要とするいくつかの「操作」オブジェクトを生成します。
- 各「操作」には、から応答データを受信するために使用される
Handler
ラップが含まれています。Messenger
Service
- 操作が実行されると、操作はにラップ
Messenger
されてIntent
呼び出さstartService()
れ、メッセージがリモートサービスに渡されます。 - リモートサービスは、のパラメータに基づいていくつかの作業を行い、その操作のためにに
Intent
を送信することによって応答を返します。Message
Messenger
操作に存在する基本的なコードは次のとおりです。
public class SessionOperation {
/* ... */
public void runOperation() {
Intent serviceIntent = new Intent(SERVICE_ACTION);
/* Add some other extras specific to each operation */
serviceIntent.putExtra(Intent.EXTRA_EMAIL, replyMessenger);
context.startService(serviceIntent);
}
private Handler mAckHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//Process the service's response
}
};
protected Messenger replyMessenger = new Messenger(mAckHandler);
}
そして、サービスがどのように構成されているかのスニペット(基本的IntentService
にはキューが空のときにシャットダウンしない):
public class WorkService extends Service {
private ServiceHandler mServiceHandler;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//If intent has a message, queue it up
Message msg = mServiceHandler.obtainMessage();
msg.obj = intent;
mServiceHandler.sendMessage(msg);
return START_STICKY;
}
private void onHandleIntent(Intent intent) {
Messenger replyTarget = intent.getParcelableExtra(Intent.EXTRA_EMAIL);
/* Do some work */
Message delivery = Message.obtain(...);
replyTarget.send(delivery);
}
}
これはすべて素晴らしくうまく機能します。いくつかの異なるアプリケーションから同じサービスに大量の操作を送信でき、それらはすべて処理され、適切な場所に応答を送信します。でも...
アプリケーションが十分に長く実行され、十分なアクティビティがあると、がクラッシュすることに気づきましたOutOfMemoryError
。MATでHPROFデータを見ると、これらすべての操作がメモリに残っていることに気付きました。これらの操作は、ガベージコレクターから人質にされていましたMessenger
。どうやら、Messenger
インスタンスは、GCルートとしてカウントされるBinderへの長期ネイティブ接続を作成しており、各「操作」オブジェクトを無期限にメモリに保持しています。
Messenger
「操作」が終了したときにこのメモリリークが発生しないようにクリアまたは無効にする方法があるかどうか誰かが知っていますか?Service
同じ方法でIPCをに実装して、複数の異なるオブジェクトが要求を行い、非同期で結果を取得できるようにする別の方法はありますか?
前もって感謝します!