web-dev-qa-db-ja.com

向きの変更を処理するためのベストプラクティス:Android

スレッドとAsyncTaskを使用して向きの変更を処理するために、さまざまな方法を試してみました。私は次の解決策に出くわしました:

  1. Attach-detach model:インスタンスを保持しながら、アクティビティをスレッドおよびAsyncTaskにアタッチおよびデタッチします。 (出典: 12

  2. ヘッドレスフラグメントの方法:非UI /ヘッドレスフラグメントを使用して、スレッド関連のすべての操作を実行し、構成の変更時にそのインスタンスを保持します。 (出典: 12

このシナリオを処理する他のアプローチはありますか?推奨される方法は何ですか? Androidドキュメントでどこにも一般的な解決策を見つけることができなかったので、私はこれを求めています。

33
Gaurav Arora

いくつかの要約

上記の方法にはいくつかの良い方法がありますが、簡単な説明で要約するとよいでしょう。以下は、httpネットワーキング、非同期作業/スレッド化、およびキャッシングに現在使用されている最も人気のあるライブラリの一部です。

現在のプロジェクト(設定のみ)

私は現在OttoLoadersVolleyOrmlite、およびに基づくネットワークスタックApacheおよびServices。ネットワークスタックをVolleyRetrofit、そして多分最終的にはRobospice

個人的にオットーとボレーにとても似ています


RoboSpice(モジュラー)

  • https://github.com/octo-online/robospice
  • http://www.youtube.com/watch?v=ONaD1mB8r-A
  • 実行時間の長いタスクへのプラグイン/モジュール式アプローチ
  • これはライブラリの「スイスアーミーナイフ」に似ていますが、各ツールの機能を知っておく必要があります。
  • 処理REST呼び出し
  • 方向やその他の変更を通じてデータを保持します
  • ディスクとメモリのキャッシュを処理できます)
  • さまざまなHTTPライブラリおよび永続化ライブラリ(Gson、Jackson、Spring、 OkHttp 、および以下のライブラリの多く)で動作します
  • Ormlite サポートのベータ版、

レトロフィット(REST)

Volley(ネットワークデータと画像)

Picasso(画像)

ローダー(Android)

  • よくサポートされています
  • 向きの変更とフラグメントの状態の保存/読み込みを継続します
  • 正しく理解するのは難しい場合があります
  • キャッシングなし

AsyncTask(Android)

  • uIスレッドからのバックグラウンド作業の簡単な方法
  • キャンセルする必要があり、アクティビティまたはフラグメントが破棄された後に戻るタスクに注意してください。

オットー(イベントバス)

  • https://github.com/square/otto
  • コンポーネントとフラグメント間の非同期作業を容易にするイベントバス
  • とてもパワフルな @Produce能力は最後のイベントを保持し、バスに関心のある新しいサブスクライバーに対してオンデマンドで生成できます。

ヘッドレスフラグメント(?)

  • 私は個人的にこれがVogellaのチュートリアル以外に使用されたのを見たことがないので、これについてはわかりません。

サービス(Android)

  • 古い学校の方法
  • 究極のコントロール、あなたは自分ですべてをしなければなりません
  • 通常、AppacheまたはHURLクライアントで使用され、
  • インテントを介して小包を渡す
43
pjco

Loaders 、特にAsyncTaskLoaderを試してみませんか?それらは Support Library を通じてpre-Honeycombで利用可能であり、アクティビティ/フラグメントのライフサイクルに完全に一致します。ここに公式の要約があります:

  • それらはすべてのアクティビティとフラグメントで利用できます。
  • データの非同期読み込みを提供します。
  • 彼らはデータのソースを監視し、コンテンツが変更されたときに新しい結果を提供します。
  • これらは、構成変更後に再作成されるときに、最後のローダーのカーソルに自動的に再接続します。したがって、データを再クエリする必要はありません。
7
a.ch.

実際にはRoboSpiceライブラリを使用しています。これは、RequestListenersオブジェクトのみを提供するサービスで実行されます。

最初のアプローチの問題(AsyncTask間で参照を保持する)は、おそらく生成できるメモリリーク AsyncTasksがアクティビティ参照を保持している場合、ガベージコレクションされないため。同じアクティビティを何度も繰り返してヒープサイズをチェックするアプリケーションをプロファイリングするだけで、これに注意してください。ヒープは通常のパラメータで増加するはずです(ガベージコレクションの対象となるオブジェクトが新しいオブジェクトと同時に存続する瞬間があります)が、GCが実行されると、RAM割り当ては最初に割り当てたサイズと同じです。

だから私が何かを勧めなければならないなら、次のことになるでしょう:

APIの呼び出しとフローを管理するアクティビティ(RoboSpiceを使用すると、UIを回転させることができます)RetainInstanceをtrueで使用するFragments内のシンプルな画面。これにより、DTOを直接フラグメントに渡すことができ、最上位のアクティビティで状態を管理するだけで済みます。

4
noni

AsyncTaskの処理が主な懸念事項である場合、つまり方向が変更されるたびにデータをダウンロードしたくない場合は、次のようにしてみてください-

(1)このように作成する前に値を初期化します..

Boolean Android_hacker = false;

(2)ここで、AsyncTaskクラスでのデータのダウンロードが完了したら、その値をtrueに設定します

Android_hacker = true;

ここでは、モデルとアレイアダプタークラスを利用してすべてのデータを維持します。

(3)向きが変わるたびに、このように確認してください

if( Android_hacker = true ){

// Use your saved instance ..

}else{

// Download data as it is yet not downloaded ..

}

それが役に立てば幸い ..

3
AndroidHacker

AsyncTask以外にもさまざまな方法があります。また、ベストプラクティスを見つけようとする場合、AsyncTaskは適切なオプションではありません。 この回答 は、AsyncTaskを使用してはならない理由を説明しています。また、長時間実行されるタスクに対処できるより優れた方法 RoboSpice を使用することをお勧めします。
すでにこのライブラリを使用しており、試してみる価値があると思います。アクティビティのライフサイクルを尊重し(向きの変更)、メモリリークがなく、マルチスレッドをサポートし、結果をキャッシュします...長いリクエストタスクをプラグアンドプラグ解除できますキャッシュを使用する(ただし、キャッシュ以外のリクエストではうまく機能しません)。

しかし、私はGoogleからの良い方法をお勧めします:IntentServiceおよびBroadcastReceiver。データの結果を受信するために、方向転換中にブロードキャストを登録および未登録します。すべてのバックグラウンドタスクはIntentServiceで機能し、BroadcastReceiverによってアクティビティにしたいことをすべて通知します。あなたが試すことができる多くの例があります。このようなもの: http://mobile.tutsplus.com/tutorials/Android/android-fundamentals-intentservice-basics/

更新

こんにちはR4j、私のアプリケーションは静かで複雑です。そして、私は多くの並列ネットワーク呼び出しを行わなければなりません。 IntentServiceによるアプローチは優れていますが、複雑なシナリオには適していません

これは問題ではないと思います。 IntentServiceを使用すると、複雑なタスクも含めて何でも実行できます。並列タスクが必要な場合は、マルチスレッド化されたサービスを検討し、インテントによるアクティビティと通信することができます。サービスとアクティビティの間でインテントを送信することは安全で柔軟です。つまり、Android方法です。
そして、(ファイルのダウンロード、ストリーム、データベースによって)キャッシュしたい場合は、RoboSpiceが最適です。

2
R4j