14

Web から読み込んだ画像を保存する必要があるかどうか (およびその方法) に関する質問がありました。Android アプリから Web サービスを呼び出しているとします。この Web サービスでは、Web 上の画像の URL を取得します。この画像をダウンロードして、ListView のリスト項目の左側に表示します。私の質問は、画像を保存するためにどの方法を使用すればよいですか? するべきか:

  1. SDCard に保存し、ListView の作成時に (後続の要求で) 存在するかどうかを確認し、必要に応じて再ダウンロードします (画像が変更された場合に時々更新しながら)。
  2. Context.getCacheDir() を使用してキャッシュに保存しますが、画像がキャッシュに残っていることに頼ることができないため、より頻繁に再ダウンロードを余儀なくされる可能性があります。
  3. 常にダウンロードし、イメージを保存しないでください。

画像ファイル自体はかなり小さいですが、これらの小さな画像を何十枚もダウンロード/保存するユーザーもいると思います。どの方法が最も効果的ですか?また、推奨される方法は何ですか?

副次的な質問として、最初に ListView にすべての画像をロードする (そして、しばらくの間 UI をロックする可能性がある) か、非同期にロードしてその間にプレースホルダー グラフィックを表示する必要がありますか (これはもう少し「醜い」かもしれません)。ここの基準は?

4

4 に答える 4

21

保存場所について: 答えは、ダウンロードされるものとその量によって異なります。次に、選択を行います。

例: 一時的で、数が少なく (リモート フェッチが少なく) サイズが小さく (メモリが少なく)、アクティビティに対してローカルなものをダウンロードする場合は、SoftReferences を使用してメモリ内に画像を保持することを検討する必要があります。SoftReferences は再フェッチにつながる可能性がありますが、アイテムの数が少ないため、手頃な価格である必要があります。

ただし、ダウンロードするアイテムの数が特定のしきい値を超えた場合 (つまり、フェッチとメモリが増えることを意味します) は、キャッシュすることでフェッチとランタイム メモリの消費を減らすことを検討する必要があります。ここで、SD カードまたは一時ストレージ (アプリのローカル キャッシュ ディレクトリ) に保存することを選択できます。小さく、アプリケーションのコンテキストでのみ意味を持つアイテム (サムネイルなど) の場合、ユーザーはほとんどの場合、アプリケーションの外では使用しません。したがって、そのようなものをキャッシュディレクトリに保存できます。それらを使用する最良の部分は、混乱をきれいにする必要がないことです。自動的に処理されます。ただし、再フェッチにつながる可能性があります。

ただし、ダウンロードしたアイテムのサイズが大きく、写真、ビデオ、オーディオ クリップなどのアプリケーションのコンテキスト外で独立できる場合は、SD カードを選択する必要があります。また、お読みください: BitmapFactory.decodeStream(..) 中の OOM エラーを回避するための大きなビットマップの処理

データベースの使用がここで役立つかどうかを確認することもできます。これを見る

ListView で項目を遅延読み込みする際の考慮事項: 読み込みはバックグラウンドで実行し、UI スレッドをブロックしないようにする必要があります。項目のダウンロード中に一時的な画像を表示することを検討する必要があります。これは、多くのネイティブ アプリケーションで明らかです。遅延読み込みの実装例については、こちらを参照してください。さらに、大きなリストの場合は、SlowAdapter パターンを実装できます (API デモを確認してください)。リストがスクロールしている間、基本的にダウンロードが停止します。

ここで役立つサンプル プロジェクト:

Romain Guy の Shelves プロジェクトでは、2 レベルのキャッシュを使用しており、彼はインメモリ キャッシュ (SoftReferences を含む HashMap) と Sdcard 上のストレージを採用しています。ここでソースコードを参照

また、Mark Murphy が作成したオープン ソース ライブラリ (CWAC) と、ここで役立つ DroidFu もあります。

幸運を!

于 2010-01-13T08:58:37.170 に答える
3

あなたの「副次的な質問」に関しては、非同期でロードすることが好ましい動作だと思います。特に、ネットワークトランザクションでは、「しばらくの間UIをロックする」だけでなく、「ロックする」ことも考慮する必要があるためです。 UIがロードされない場合に備えて、「UIを永続的に」。

ただし、この動作を醜いと考える場合は、いくつかの画像を読み込む機会を与えるタイマー(1秒または2秒)を設定できます。すべての画像が読み込まれた場合、またはタイマーの期限が切れた場合は、先に進んでUIを表示してください。とにかくプレースホルダー画像を使用して、残りを非同期でロードします。これはとにかく永続的なロックを防ぐために行く方法です。

あなたの質問の最初の部分に関しては、それはあなたが表示している画像の文脈とタイプにいくらか依存していると思います。ただし、ほとんどのWebアセットでは、同じセッションで複数回ダウンロードしたくないので、#2が推奨されるアプローチだと思いますが、永続的なストレージを使い果たしたくない場合もあります。

于 2010-01-13T06:28:15.197 に答える
1

あなたの「副次的な質問」に関しては、特にネットワークトランザクションでそれを考慮する必要があるため、非同期でロードすることが好ましい動作になると思います。「UIをしばらくロックする」だけでなく、「ロックする」ロードされない場合に備えて、UI を永続的に」にします。

これを回避するには、droid-fu によるWebImageViewについて話している場合は 、ImageLoader.java initialize() 関数をこれに変更できます。

    static int alive=-1;
   public static synchronized void initialize(Context context) {

        if (executor == null) {        
           executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(DEFAULT_POOL_SIZE);           
       }
        else if(alive==executor.getActiveCount()){
               executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(DEFAULT_POOL_SIZE);
           }
       alive=executor.getActiveCount();
       if (imageCache == null) {
           imageCache = new ImageCacheHope(context, 25, 5);
       }
   }
于 2010-08-22T15:53:15.687 に答える
0

キャッシングを透過的に処理する Android イメージ マネージャー (メモリとディスク) を作成しました。コードは Github にあります https://github.com/felipecsl/Android-ImageManager

于 2013-02-12T06:01:02.403 に答える