2

私はかなりトリッキーな状況にあり、最適なデザインを決定しようとしています。基本はこれです:

  • 私は電子メールと同様のインターフェースを備えたメッセージングシステムを設計しています。
  • ユーザーが添付ファイルのあるメッセージをクリックすると、そのメッセージのテキストと、追加の添付ファイルがあることを示すペーパークリップを表示するアクティビティが生成されます。
  • この時点で、添付ファイルのプリロードを開始して、ユーザーが添付ファイルをクリックしたときに、より速く読み込まれるようにします。
  • 現在、ユーザーが添付ファイルをクリックすると、ダウンロードが完了するまで読み込みダイアログが表示され、ダウンロードが完了すると、別の添付ファイルビューアアクティビティが読み込まれ、bmpバイト配列が渡されます。
  • 添付ファイルを永続ストレージに保存したくありません。

私が抱えている問題は、回転やホームボタンの押下などをサポートすることです。ダウンロードは現在、スレッドとハンドラーのセットアップで行われます。

これの代わりに、フローを次のようにしたいと思います。

  • ユーザーは以前と同じようにメッセージをロードし、プリロードは以前と同じように添付ファイルを開始します(ユーザーには表示されません)。
  • ユーザーが添付ファイルのリンクをクリックすると、添付ファイルビューアのアクティビティがすぐに生成されます。
  • ダウンロードが完了すると、画像が表示されます。そうでない場合は、ダイアログが完了して表示できるようになるまで、このアクティビティにダイアログが表示されます。理想的には、ダウンロードが再開されないことに注意してください。そうしないと、プリロードでサイクルが無駄になります。

明らかに、ダウンロードを継続し、任意に結合されたアクティビティにコールバックできる永続的なバックグラウンドプロセスが必要です。IntentServiceは、バックグラウンドスレッドで動作し、サービス(UI以外)のライフサイクルを備えているため、私のニーズにほぼ適合しているようです。しかし、それは私の他のニーズのために機能しますか?

私がやりたいことの一般的な実装は、呼び出し元のアクティビティからメッセンジャーを取得して、メッセージオブジェクトを呼び出し元のスレッドのハンドラーに送り返すことができることに気付きました。これはすべて問題ありませんが、発信者のアクティビティが停止または破棄され、現在アクティブなアクティビティ(添付ファイルビューア)が表示されている場合はどうなりますか? 新しいアクティビティを実行中のIntentServiceに動的にバインドして、新しいアクティビティにメッセージを送り返す方法はありますか?

もう1つの質問は、Messageオブジェクトに関するものです。このパッケージで任意の大きなデータを送り返すことはできますか?たとえば、「ファイルがダウンロードされました」というメッセージを返送するのではなく、ダウンロードしたファイル自体のバイト配列をディスクに書きたくないので返送する必要があります(そうする必要があります)。

私が望む行動を達成するためのアドバイスは大歓迎です。私はAndroidを長い間使用していません。特に、向きの変更やホームボタンの押下に関しては、アクティビティのライフサイクル全体で非同期プロセスを最適に処理する方法に戸惑うことがよくあります...

4

2 に答える 2

2

IntentServiceを使用して、作業を開始し、永続ストレージに投稿します。アクティビティと通信するには、アクティビティでブロードキャストレシーバーを使用し、IntentServiceからブロードキャストインテントを送信できます。

IntentServiceが機能している限り、回転とホームボタンの押下はIntentServiceに影響を与えませんが、回転すると再描画が実行され、ホームボタンはアクティビティを一時停止します。これらの理由から、AsyncTaskを完了する必要がなく、永続化する必要がない場合を除いて、AsyncTaskで非同期作業を行うことは避けてください。

メッセージはハンドラー向けであり、コンポーネント向けではありません。システムを介して情報を送信するための基本的なアフォーダンスは、インテントとブロードキャストインテントです。

IntentServiceは、インテントをメッセージに変換し、新しいHandlerThreadを作成し、メッセージをHandlerThreadのMessageQueueに入れ、ルーパーを起動する作業を処理するだけです。バックグラウンドスレッドで実行されるrun()は、onHandleIntent()にあるものです(これは少し単純化されています)。

于 2012-11-19T22:55:39.623 に答える
2

これを解決する方法はいくつかあります。そうです、このシナリオでは、ダウンロードプロセスを出入りする可能性のあるアクティビティから切り離すために、明らかにサービスが必要だと思います。これを機能させるには、このサービスにダウンロードキューを実装する必要があります。また、IntentServiceはこの動作をすぐに実行できるため、これを使用できます。IntentServiceで頭に浮かぶ唯一の欠点は、以前に投稿したジョブをキャンセルするのがそれほど簡単ではないことです。

ダウンロードしたデータをシリアル化することはしませんが、特に大量のバイナリデータを処理している場合は、あまり効率的ではありません。ダウンロードしたデータをメモリ内のLRUキャッシュに書き込み、そのIDを割り当てることができます。これにより、ビューアアクティビティはこのダウンロードされたデータを保持できます。

ブロードキャストインテントを使用して、特定のIDでのダウンロードが終了したことをサービスからの視聴者アクティビティに通知することもできます。これにより、表示アクティビティとダウンロードサービスの間の結合が緩くなります。

したがって、次のようになります。

  1. 添付ファイル付きのユーザーオープンメッセージ。
  2. この添付ファイルのダウンロードジョブをダウンローダーIntentServiceに投稿し、この添付ファイルに一意のIDを割り当てます。
  3. ユーザーが添付ファイルをクリックすると、Viewer Acitivtyが起動し、添付ファイルの一意のIDがこのアクティビティのパラメーターとして渡されます。
  4. ビューアアクティビティが開き、表示するコンテンツのキャッシュをすぐにチェックします。まだ完了していない場合は、読み込み中のグラフィックが表示され、ダウンローダーIntentServiceがブロードキャストインテントで「xyIDが完了しました」と叫ぶのを待ちます。xy ID ==このビューアアクティビティに渡されたIDの場合、完全にダウンロードされたコンテンツをキャッシュから取得し、ユーザーに提示します。

編集:

キャッシュに関しては、いくつかの選択を行う必要があります。これ自体はかなり幅広いトピックだと思うので、ここでは以前のプロジェクトに基づいていくつかのアイデアを書きます。

上記では、メモリ内のLRUキャッシュについてのみ説明しました。これは、カスタムApplicationオブジェクトに存在するか、シングルトンとして存在します。これは邪悪な地球規模の国家を利用していますが、このような状況では合理的だと思います。利点は、ダウンロードしたデータをどこでもシリアル化する必要がないことです。ダウンロードが完了し、コンテンツがメモリに保存され、ビューアアクティビティからすぐにアクセスできます。欠点は、このデータがこのキャッシュから削除されない限り、またはメモリの状態が低いためにシステムがアプリケーションのプロセスを強制終了しない限り、このデータが利用可能になることです。

この揮発性メモリ内キャッシュの内容が失われた場合にデータが再ダウンロードされないようにするには、永続レイヤーを追加する必要があります。たとえば、ダウンロードしたデータをアプリケーションのキャッシュディレクトリに書き込みます。これにより、ダウンロードしたデータをディスクに書き込むオーバーヘッドが発生しますが、システムによってプロセスが強制終了された場合でも、少なくとも後でアクセスできるようになります。2レベルのキャッシュアプ​​ローチを使用して、この永続キャッシュをメモリ内キャッシュと組み合わせるか、いずれかを選択できます。ユニバーサルイメージローダーなど、インスピレーションを得るためにこの動作を実装する、広く使用されているイメージダウンローダーライブラリを確認することをお勧めします。

于 2012-11-19T22:56:04.840 に答える