4

質問:

AndroidでMessengerからMessengerへの通信を使用する場合と比較して、HandlerからHandlerへの通信を使用する方が「良い」(=高速でオーバーヘッドが少ない)ですか?

状況:

一連のアクティビティと 1 つのサービスが実行されている (開始されたサービス) Android アプリ。サービス内では、サービスのメイン スレッドの隣でいくつかのスレッドが実行されています。アプリケーションが開始され、最初のアクティビティがサービスを開始し、サービスが開始され、最初のアクティビティが 2 番目のアクティビティに転送され、2 番目のアクティビティがサービスにバインドされます...

ハンドラーからハンドラーへ:

...service はサービス ハンドラへの参照を渡し、2 番目のアクティビティは独自のハンドラを定義し、2 番目のアクティビティはサービス ハンドラを使用してサービスと直接通信できるようになりました。アクティビティ ハンドラに返信する必要があることをサービス ハンドラに知らせるには、 Messageオブジェクト内のmsg.objフィールドを使用して「返信先」ハンドラ (アクティビティ内のハンドラ) を設定します。これで、アクティビティとサービスの間の双方向通信が正常にセットアップされました。

メッセンジャーからメッセンジャーへ:

...サービスはサービス メッセンジャーへの参照を渡し、2 番目のアクティビティは独自のメッセンジャーを定義し、2 番目のアクティビティはサービス メッセンジャーを使用して間接的にサービスと通信できるようになりました。サービス メッセンジャーはメッセージ (Message オブジェクト) を Parcelable オブジェクトに変換し、Parcelable を再変換します。オブジェクトを新しい (ただし等しい) Message オブジェクトに戻し、サービスのハンドラーに引き渡します。アクティビティ メッセンジャーに返信する必要があることをサービス メッセンジャーに知らせるために、アクティビティ内のメッセンジャーでmsg.replyToフィールドを設定できます。双方向通信が正常にセットアップされました。

問題":

1 つのプロセスの境界内にあるアプリでの直接通信のみが必要な場合に、Messenger から Messenger へのセットアップが必要なのはなぜですか? 1 つのプロセス内のすべてのスレッドは、ハンドラーを使用して簡単に通信できます (これらのスレッドすべてが独自のハンドラーを正しくセットアップしていると仮定します)。メッセンジャーが最初に2つのハンドラー間で共有されるメッセージオブジェクトをフラット化することを望んでいません。これは、「Androidサービスのチュートリアルにやみくもに従う」以外の目的なしにオーバーヘッドが追加されるだけです。

考えられる解決策:

サービスを開始し、一度バインドし、サービスにローカル バインダー オブジェクトを渡させ、onServiceConnected() の ServiceConnection 実装内でアクティビティ内のサービス ハンドラーを設定し、アクティビティにそれをグローバル メモリ空間のどこかに格納させ、 3 番目、4 番目、5 番目のアクティビティであり、他のすべてのアクティビティで再度バインドする必要はありません。これは、すべてのアクティビティが独自のハンドラーを認識し (各アクティビティで個別にセットアップ)、グローバル メモリ空間からサービス ハンドラーを取得できるためです。サービスが 4 番目のアクティビティのハンドラーに応答する必要がある場合、4 番目のアクティビティは独自のハンドラー (fourthHanlder) を msg.obj フィールドに追加するだけで、サービスは応答メッセージの送信先を認識します。それでおしまい。

それに加えて、アクティビティは ui-thread/main-thread で実行され、サービスは ui-thread/main-thread でも実行されるため、実際には同じスレッドの一部であり、ハンドラーが異なるだけです。それとも、これは私の間違った考えですか?

これは、Messenger 全体が、同じプロセス内のスレッド間のローカル (内部) 通信の余分なオーバーヘッドにすぎないことを意味します! メッセンジャーが同じプロセス内で相互に通信し、メッセージのフラット化をバイパスして Parcelable オブジェクトへの変換をスキップするかどうかを Android システムが内部的に判断しない限り、これは必要ありません。ユーザー/プログラマーは実際にこれを認識しています (これが私が今考えていることが本当である場合、少なくとも私はこれを認識していません)。

アクティビティとサービス間の非同期通信を作成するには、次の 3 つの方法しかないことがわかりました。

  • インテント(インテントでオブジェクトを送信することはできません!)
  • メッセンジャー(ハンドラーを直接使用する場合と比較して可能性が制限されます。たとえば、キュ​​ーの先頭にメッセージをキューに入れることはできません)
  • ハンドラー(ハンドラーが属するスレッドが同じプロセス内にある場合にのみ可能です。それ以外の場合はメッセンジャーが必要です)

ハンドラーがスレッド間で通信する最速の方法であり、メッセンジャーがそれに続き、最後がインテントであると私は信じています。これは本当ですか???

私がこれを間違って見ている場合でも、この問題に関するあなたの洞察と経験を共有してください:)ありがとう。

4

1 に答える 1