7

誰かが非同期のための良いメカニズムを作る方法を教えてもらえますか?ListView / GridViewで使用する画像をダウンロードしますか?多くの提案がありますが、それぞれが典型的な要件の小さなサブセットのみを考慮しています。

以下に、私と同僚が一度に満たすことができないいくつかの合理的な要因(要件または考慮すべき事項)をリストしました。
私はコードを求めているのではなく(歓迎されますが)、説明されているようにビットマップを管理するアプローチだけを求めています。

  1. ダウンローダーやビットマップの重複はありません
  2. 不要になった、または自動的に削除される可能性のある画像のダウンロード/割り当てのキャンセル(SoftReferenceなど)
  3. 注:アダプターは、同じIDに対して複数のビューを持つことができます(getView(0)の呼び出しは非常に頻繁です)
  4. 注:ビューがリサイクルされる代わりに失われないという保証はありません(List / GridViewのサイズ変更またはテキストによるフィルタリングを検討してください)
  5. ビューとデータ/ロジックの分離(可能な限り)
  6. ダウンロードごとに個別のスレッドを開始しない(UIの目に見える速度低下)。キュー/スタック(BlockingQueue?)やスレッドプールなどを使用しますが、アクティビティが停止した場合はそれを終了する必要があります。
  7. リスト/グリッド内の現在の位置から十分に離れたビットマップをパージする(できればメモリが必要な場合のみ)
  8. 廃棄されるすべてのビットマップでrecycle()を呼び出します。
  9. 注:外部メモリは(常にまたは常に)使用できない場合があります。使用する場合は、(ここでダウンロードした画像のみを)できるだけ早くクリアする必要があります(Androidによるアクティビティの破棄/レクリエーションを検討してください)
  10. 注:データは変更できます:エントリは削除され(複数選択と削除)、追加されます(バックグラウンドスレッドで)。リンク先のエントリがまだ存在する限り、ダウンロード済みのビットマップは保持する必要があります。
  11. setTextFilterEnabled(true)(ArrayAdapterのメカニズムに基づく場合、配列インデックスに影響します)
  12. ExpandableListで使用可能(サムネイルが表示される順序に影響します)
  13. (オプション)ビットマップがダウンロードされたら、関連するImageViewのみを更新します(リスト項目は非常に複雑な場合があります)

個別のポイントに対する回答は投稿しないでください。私の問題は、いくつかの側面に焦点を合わせるほど、他の側面がより曖昧になり、ハイゼンベルグのようになることです。
それぞれが難易度の次元を追加します。特にBitmap.recycleは、操作中およびアクティビティの破棄時に呼び出す必要があります(onDestroy、onStopでさえ呼び出されない場合があることに注意してください)。
これにより、SoftReferencesに依存することもできなくなります。
必要です。または、ビットマップをnullにした後、try-catch(制御されたOutOfMemoryを強制するため)でgc、sleep(20s、偶数)、yield、および巨大な配列割り当てをいくつでも実行した後でもOutOfMemoryErrorが発生します。すでにビットマップ
リサンプリングしています。

4

2 に答える 2

2

この例を確認してください。それはグーグルによって使用されており、私もOutOfMemoryエラーを回避するために同じロジックを使用しています。

http://developer.android.com/resources/samples/XmlAdapters/index.html

基本的に、このImageDownlaoderはあなたの答えです(それはあなたの要件のほとんどをカバーしているので)あなたがその中に実装することもできます。

http://developer.android.com/resources/samples/XmlAdapters/src/com/example/android/xmladapters/ImageDownloader.html

于 2011-12-14T10:55:18.787 に答える
0

結局、私はリサイクルのバグを完全に無視することにしました。それは、管理可能なプロセスの上に不可能な難しさの層を追加するだけです。
その負担(アダプターなどで画像の表示を停止するだけ)なしでMap<String, SoftReference<Bitmap>>、ダウンロードしたビットマップをURLで保存するために使用するマネージャーを作成しました。
また、2-4 AsyncTasks(doInBackgroundとonProgressUpdateの両方を使用します。InterruptedExceptionをスローする特別なジョブを追加することで停止します)は、LinkedBlockingDeque<WeakReference<DownloadingJob>>によってサポートされているからジョブを取得しWeakHashMap<Object, Set<DownloadingJob>>ます。
deque(以前のAPIで使用するためにコピーされたLinkedBlockingDequeコード)は、ジョブが不要になった場合にジョブを残すことができるキューです。マップにはキーとしてジョブクリエーターが含まれているため、アダプターがダウンロードを要求してから削除されると、マップから削除され、その結果、すべてのジョブがキューから消えます。

画像がすでに存在する場合、ジョブは同期的に戻ります。また、AdapterViewのどの位置に関係するかを識別できるデータのバンドルを含めることもできます。

キャッシュは、SDカード(使用可能な場合)のURLEncoded名でも実行されます。(部分的にクリーンアップされ、最も古いものから開始し、アプリの起動時に、および/またはdeleteOnExit()
リクエストを使用すると、更新を確認するために、キャッシュされたバージョンがある場合は「If-Modified-Since」が含まれます。

同じことがXML解析にも使用できます。 、および他のほとんどのデータ取得。
そのクラスをクリーンアップした場合は、コードを投稿します。

于 2013-02-05T08:51:25.890 に答える