52

次の手順を実行する必要がある Android アプリを設計しています。

  1. ユーザーがボタンを押すか、「データの同期」を指示します。
  2. 同期プロセスは、REST Web サービスを使用してサーバーとの間でデータを移動します。
  3. データは sqlite データベースにローカルに保存されます。
  4. 同期プロセスは、ステータスの更新/メッセージを UI に提供する必要があります
  5. ユーザーがアプリケーションの他の部分に移動して、同期プロセス中にさらに作業を行うことを許可しないでください。

初めて同期プロセスを実行するときは、10 ~ 20 分かかる場合があります。最初の同期後、転送および保存されるデータは少なくなり、プロセスにかかる時間は 1 ~ 2 分以内になると思います。

私はアンドロイドAsyncTaskとサービスを使用するさまざまな例について多くのことを読んできました...しかし、設計上の考慮事項と、ある設計を他の設計よりも選択する際のトレードオフを完全には理解していません。現在、AsyncTask を使用してデモ プロジェクトをスタブ化しています。(ほとんどの) Android REST クライアント アプリケーションの開発を見た後 : http://code.google.com/events/io/2010/sessions/developing-RESTful-android-apps.html#おそらく私はまだ「理解していない」だけなので、過度に複雑に感じます.

私は、Java、Spring、Web、およびデスクトップ アプリケーションのバックグラウンドを持っています。ハンドヘルド デバイスの観点から考えて設計することは、私にとってまったく新しいことです。(画面レイアウトが変更された場合はどうなりますか?同期の実行中に電話が鳴ったらどうなりますか?) 最初の同期が非常に長時間実行されるプロセスになる場合、2 歩戻って、より良い方法はありますか?私は問題について考えます->解決策、ユーザーエクスペリエンス、電話で実行されているアプリケーションに対するユーザーの期待?

すでにこれらの質問に取り組んでいる、経験豊富な Android 開発者の意見をぜひお聞かせください。

4

5 に答える 5

44

私の意見では、これはメインストリーム/平均的な Android 開発の中で最もトリッキー/難しい部分です。たとえば、BlackBerry では、これは数倍簡単です。

必ず a を使用する必要がありますService

AsyncTaskActivityハンドルを介してしっかりと「バインド」されているため、適切ではありません (そうしないと、から のContextUI を更新できません)。ただし、バックグラウンドに入ると、OS によって強制終了される可能性があります。バックグラウンドに移行する理由の例としては、電話の着信が考えられます。ユーザーが電話アプリケーションに切り替えると、あなたが非表示になります。この場合 (現在の RAM の状態に応じて)、OS はバックグラウンド (ユーザーには見えない) アクティビティの 1 つを強制終了することを決定する場合があります。ActivityAsyncTaskActivityActivityActivity

一部の開発者は、内部で長時間実行されるアクションを持つための静的なものを配置することで、これを回避します。Applicationインスタンスの使用を推奨する人もいます。これは、Applicationアプリ プロセス全体が存在している間に静的なものが存在するためです。ただし、これらは不適切な回避策です。Android のプロセスも、OS がその時が来たと判断したときに強制終了される場合があります。Android OS には、何をどのような順序で強制終了できるかについて独自の考慮事項があります。すべてのプロセスは、「殺傷能力」の 5 つのレベルに分けられます。これらのレベルが指定されているドキュメントは次のとおりです。そこで読むのは興味深いです:

サービスを実行するプロセスは、バックグラウンド アクティビティを実行するプロセスよりも上位にランク付けされるため、長時間実行される操作を開始するアクティビティは、単にスレッドを生成するのではなく、その操作のサービスを開始するのに適している場合があります。アクティビティ。たとえば、バックグラウンドで音楽を再生したり、カメラで撮影した写真を Web サイトにアップロードしたりします。 サービスを使用すると、アクティビティに何が起こっても、操作が少なくとも「サービス プロセス」の優先度を持つことが保証されます。

ユーザーActivityが実行時間の長いアクションを開始するProgressDialog場所には、アクションの実行中にユーザーが他に何もしないことを確認するために が表示されます。ガイドはこちらです。

NotificationManagerまた、 が現在非表示の場合、長時間実行アクションの完了 (または失敗) についてユーザーに通知するために を使用する可能性が最も高いでしょうActivity開始するNotificationManager 情報は次のとおりです。

于 2010-11-14T11:57:22.437 に答える
12

自分の状況にどのようにアプローチするかを最もよく決定するために検討しなければならない考慮事項が複数あります。2つのアプローチを適切に比較する必要があるようです...ここに、ハンドヘルドデバイスで作業するときに考慮しなければならない類似点、相違点、および追加の考慮事項のリストを示します。

サービスは、UIを持たないアプリケーションの一部です。UI(アクティビティ)によって呼び出されて開始される場合と、アプリケーションの他のコンポーネントによって開始される場合があります。開発時には、別のスレッドに配置したり、別のタスクやプロセスで実行したりすることができます。これにより、最終的にUIから分離することができます。さらに、必要に応じて、サービスを開始して独立して実行する(startService)か、アクティビティをサービスにバインドする(bindService)ことができます。カスタムハンドラーを使用すると、コールバックを設定して、進行状況に応じてUIを更新できます。ユーザーがアクティビティを変更した場合、サービスは必ずしも終了するわけではありませんが、OSによっていつでも終了される可能性があります。

AsyncTaskは、常にUIスレッドからインスタンス化されます。特定のコールバックのみを許可しますが、アクティビティによって実行されるアクションに本質的に関連付けられている比較的短いトランザクション(専用の個別のスレッドサービスと比較して)の目的で、マルチスレッドのプロセスを簡素化します。ユーザーがアクティビティを変更するたびに、AsyncTaskは「一時停止」になり、アクティビティのUIスレッドがなくなったために停止することもあります。

私が最も心配しているのは、アプリが最初に10〜20分かかる場合、ユーザーが一時的にタスクを変更するか、完了するまで電話を置くと想定します(これにより、すべての原因となる可能性があります)電話がスリープしている場合も同じ問題が発生します)。この考慮事項を考慮すると、アクティビティにバインドされたスレッドサービスが最良の選択である可能性があります。UIを保護するために、進行状況のコールバックを受け取るアクティビティの進行状況ダイアログを作成します。これにより、アプリへのユーザー入力が制限され、サービスが必要な方法で継続できるようになります。次に、アクティビティonResumeをオーバーライドして、サービスのステータスと実行中かどうかを確認します。その後、ダイアログをすぐにリセットできます。

これが私の好ましい方法であることを考えると、OSがとにかくいつでもアプリを強制終了する可能性があることも考慮に入れます。したがって、不完全または部分的な同期を検出する方法があることを確認してください。その後、アクティビティまたはサービスが再起動すると、自動的に再開できます。

于 2010-11-09T14:16:26.363 に答える
5

ユーザーが別のアクティビティにAsyncTask移動した場合、そのオブジェクトを他のアクティビティに転送できないため、そのオブジェクトは終了します。ユーザーが画面を回転させたり、そのようなことをしたりするときにプレイできるトリックがありますが、それは一般的な目的の破壊には及びません。 AsyncTaskランダムに死ぬことができます。

同期が完了するまでに時間がかかることがあるため、Google Sync はバックグラウンドでサービスとして実行されます。彼らの道をたどって、通信できる独自の同期サービスを作成する必要があるかもしれません。これを達成するためのいくつかの考えを次に示します。

http://mylifewithandroid.blogspot.com/2008/01/about-binders.html

Service と Activity の間で確実に通信できますが、正しく行うのは難しいです。

于 2010-09-28T23:01:17.240 に答える
3

選択は主にアプリの設計に依存します。AsyncTask と IntentService はどちらも独自の立場にあるため、アプリ (ユーザー エクスペリエンス) に求めるものの方が重要であり、どちらかまたは両方を選択します。いくつかのシナリオを以下に示します (主にアプリの開発中に経験したもの)

  • フィード ページを持つアプリを想定します。ページを表示可能にするために複数の API 呼び出しが行われる場合 (/getFriends、/getDates、/getPictures など)、そのようなすべての API 呼び出しを、マルチスレッド化されたエグゼキューターを使用して単一の AsyncTask にワープできます。実行順序は関係ありません。単一のワーカー スレッドですべての呼び出しを順番に実行する IntentService とは対照的です。マルチコアのハイエンド デバイスの場合、AsyncTask からの呼び出しがより効果的です。また、UI スレッドで AsyncTask を開始すると、IU の更新は簡単です (ボイラー プレート コードを読む必要はありません)。また、ユーザーがページを離れても、コンテキストを保持しないという賢明な使用により、アプリはクラッシュしません。

  • ユーザーがビュー/アクティビティ/フラグメントにいる必要がなく、何かを表示するための合計実行時間がミッションクリティカルではないアプリを作成しようとしていると仮定すると (同期サービスまたはユーザー通知/アラームを想定)、IntentService の方が優れています。選択。(UI スレッドで Asynctask を開始する手間がかからないため、UI などの変更を強制するハンドラーを作成する必要がなく、ボイラー プレート コードが少なくなります)

私の経験から-両方の小さなアプリを作成し、長所と短所を比較してより良いアイデアを得る. (ps より良いアイデアを得るために、Google の iosched アプリを参照することをお勧めします - それらは Asynctask と IntentService の両方を使用します)

于 2013-02-25T23:05:52.573 に答える
2

私は IntentService + BroadcastReceiver の組み合わせを好む傾向があります。なぜなら、それらは非常に強力な制御を提供するからです

画面上の何かを更新する場合は、必ず UI が実行されていることを確認する必要があります。ASyncTask のクラッシュは、Android のクラッシュの主な原因の 1 つであることがすぐに報告されました。これは、ある種の「activityIsAlive」変数を保持し、アクティビティが停止している場合は UI の更新をスキップまたは遅延することで回避できます。

IntentService + BroadcastReceiver の組み合わせは、ほとんどのチュートリアルで BroadcastReceiver の onPause または onStop を停止するように指示されているため、クラッシュに対する耐性が少し高くなります。これを行わないと、UI の更新をオフにする必要があります。UI の更新に役立つ runOnUiThread コマンドがどこかにあります。

IntentService + BroadcastReceiver の組み合わせもより拡張可能です。関数を作成し、BroadcastReceiver を拡張して、より洗練された REST 処理ソリューションを作成できます。ただし、ASyncTask よりも多くの配管が必要です。

UI の更新を遅らせる場合は、OnWindowFocusChangedListener でリグできる場合があります。その関数が true を受け取ると、UI が生きていることを意味します。

tldr; バックグラウンドで何かを実行している場合は、UI を更新する前にアクティビティやフラグメントが有効であることを確認してください。

2015 編集: ローダーもチェックしてください。舞台裏で多くのことが起こっているため、把握するのが少し難しい

于 2014-09-13T22:39:09.777 に答える