web-dev-qa-db-ja.com

Androidクライアントがスレッドを使用してサーバーと通信するためのベストプラクティス

私はAndroidアプリを構築しています。アプリが実行されている限り、定期的にサーバーと通信します。

これを行うには、アプリの起動時にサーバーへの接続を開始します。次に、threadというメッセージを受信するための別のReceiverThreadを用意します。このthreadは、socketからメッセージを読み取り、分析して、アプリケーションの適切な部分に転送します。

このthreadはループで実行され、読み取る必要があるものをすべて読み取り、新しいデータが到着するまでread()コマンドでブロックします。そのため、ほとんどの時間はブロックされます。

SenderThreadと呼ばれる別のスレッドを介してメッセージの送信を処理します。私が疑問に思っているのは、SenderThreadを同様の方法で構造化する必要があるかどうかです。つまり、このスレッドのキューを維持し、キュー内のすべてのメッセージを送信してから、新しいメッセージがキューに入るまでブロックするか、メッセージを送信する必要があるたびにスレッドの新しいインスタンスを開始する必要があるのか、メッセージを送信してから「死ぬ」ようにしますか?私は最初のアプローチに傾いていますが、パフォーマンス(ブロックされたスレッドをメモリに保持するか、新しいスレッドを初期化するか)とコードの正確さの両方の点で実際に優れている点はわかりません。

また、すべてのアクティビティでメッセージを送受信できるようにする必要があるので、Applicationクラスの両方のスレッドへの参照を保持しているので、それは許容できるアプローチですか、それとも別の方法で実装する必要がありますか?

これで遭遇した1つの問題は、アプリケーションを閉じて再度実行すると、実際にはReceiverThreadのインスタンスが2つあるため、メッセージが2回表示されることがあります。

これは、アプリケーションが実際には閉じず、前のスレッドがまだアクティブであり(read()操作でブロックされている)、アプリケーションを再度開いたときに、新しいスレッドが初期化されたためと思われますが、両方ともサーバーに接続されているため、サーバーは両方にメッセージを送信しました。この問題を回避する方法、またはそれを完全に再編成して正しいようにする方法に関するヒントはありますか?

私はこれらの質問を調べてみましたが、私の最初の質問にはいくつかの矛盾する例が見つかりました。

14
Bob

1。あなたが本当にを維持する必要がある場合、あなたのアプローチは大丈夫ですいつでもサーバーとクライアント間の接続をオープンにします。ただし、HTTP要求をサーバーに送信するような非同期接続を使用し、サーバーがそのように感じるといつでも応答を取得します。

サーバーが後でクライアントに応答する必要があるが、いつかわからない場合は、 Google Cloud Messaging framework を調べることもできます。これにより、透過的で一貫した方法が得られますサーバーからクライアントに小さなメッセージを送信する。

モバイルアプリケーションを開発するときは、いくつかの点を考慮する必要があります。

  1. スマートフォンのバッテリーは無限大ではありません。

  2. スマートフォンのインターネット接続はやや不安定で、さまざまなタイミングでインターネット接続が失われます。

常にサーバーへの直接接続を維持すると、アプリはキープアライブパケットを送信し続けます。つまり、電話をかなり速く乾かします。インターネット接続がモバイルブロードバンドと同じくらい不安定な場合、接続が失われることがあり、これから回復する必要があります。したがって、TCPを使用する場合、パケットを確実に受信したいため、同じパケットを何度も再送信する必要があるため、オーバーヘッドが大きくなります。

また、サーバー側でスレッドを開いた場合、サーバー側でスレッドの問題が発生する可能性があります。同時に200台のクライアントがサーバーに接続しているとします。各クライアントは、サーバー上で1つのスレッドを開いています。サーバーが同時に200の異なるスレッドを処理する必要がある場合、これは最終的にサーバーにとって非常にパフォーマンスを消費するタスクになる可能性があり、自分自身でも多くの作業を行う必要があります。

2。アプリケーションを終了するときは、クリーンアップする必要があります。これは、アクティブなonPauseActivityメソッドで行う必要があります。

つまり、すべてのアクティブなスレッドを強制終了し(または少なくともそれらを中断し)、UIの状態を保存し(必要な場合)、サーバーへの開いている接続をすべてフラッシュして閉じます。

Threadsの使用に関しては、 Handlers または AsyncTask のような組み込みのスレッド化ツールを使用することをお勧めします。

Threadを使用する方法を本当に考えているのであれば、スレッドの「マネージャー」として Singleton pattern を使用することをお勧めします。

このマネージャーはスレッドを制御するため、アプリケーションの別の部分にいる場合でも、特定の時間に複数のThreadがサーバーと通信することはありません。

Applicationクラスの実装に関する限り、 アプリケーションクラスのドキュメント をご覧ください。

グローバルなアプリケーション状態を維持する必要がある人のための基本クラス。 AndroidManifest.xmlのタグで名前を指定することにより、独自の実装を提供できます。これにより、アプリケーション/パッケージのプロセスが作成されるときに、そのクラスがインスタンス化されます。

通常、アプリケーションをサブクラス化する必要はありません。ほとんどの状況で、静的シングルトンは、よりモジュール的な方法で同じ機能を提供できます。

したがって、独自のApplicationクラスを実装しないようにすることをお勧めしますが、Activitiesの1つに独自のSingletonクラスを初期化させ、Threadsおよびシングルトンの初期化が特定のActivityに「バインド」される可能性があるため、特定のActivityが画面から削除されて一時停止すると、接続が問題になる可能性がありますシングルトンも殺される可能性があります。したがって、Application実装内でシングルトンを初期化することは、有用であると見なされる場合があります。

テキストの壁で申し訳ありませんが、あなたの質問はかなり「自由回答」なので、私はあなたに多少自由回答の質問を与えようとしました-それが役に立てば幸いです;-)

20
Darwind