2016-09-16 13 views
0

私のアプリでは、いくつかのサムネイルを含む異なるリストビューを持っています。 私はリファクタリングを開始しており、LRUキャッシングを実装したいと考えています。私はAndroidのガイドラインに従っていますが、アプリケーション全体で1つのLRUキャッシュを初期化する方が良いか、リストビューごとにLRUキャッシュを初期化する方がいいかと思います。 私はoutOfMemoryを恐れています。 したがって、私は自分自身で答えることができない以下の質問があります。 - シングルトンパターンで初期化された1つのLRUキャッシュは良いアイデアですか? - メモリが少ない場合、LRUキャッシュの次の初期化からoutOfMemoryが発生しますか?メモリが不足している場合にLRUキャッシュ:アプリケーション全体で1つだけ初期化しますか?

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    ... 
    // Get max available VM memory, exceeding this amount will throw an 
    // OutOfMemory exception. Stored in kilobytes as LruCache takes an 
    // int in its constructor. 
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024); 

    // Use 1/8th of the available memory for this memory cache. 
    final int cacheSize = maxMemory/8; 

    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { 
     @Override 
     protected int sizeOf(String key, Bitmap bitmap) { 
      // The cache size will be measured in kilobytes rather than 
      // number of items. 
      return bitmap.getByteCount()/1024; 
     } 
    }; 
    ... 
} 
  • 、LRUキャッシュは自動的に解除されますか?私はLRUキャッシュ(メモリが足りないためアプリクラッシュ)を使用するとアプリがメモリを解放するのに問題があるのだろうかと思っています。

  • アプリ全体に1つのLRUキャッシュしかありませんか?

  • アプリ全体で複数のLRUキャッシュが問題になることはありますか?

答えて

1

私はこれに多くの問題を抱えていましたので、ここで役立つ答えをいくつか教えてください。

メモリが少ない場合、LRUキャッシュは自動的に解放されますか?私はLRUキャッシュがない自動的にメモリを解放しますLRUキャッシュ

を使用する場合、アプリケーションがメモリを解放する問題を持っている場合、私は思ったんだけど。プログラムでエントリを削除する必要があります。

アプリ全体に1つのLRUキャッシュしか問題ありませんか?

アプリ全体で複数のLRUキャッシュが問題になることはありますか?

LruCacheクラスは、キーのタイプと値のタイプを持つ汎用クラスです。私はあなたがキャッシングしているオブジェクトの種類ごとに1つのLRUキャッシュを持ちたいとします。あなたは私がやったことをやっている:Bitmapをキャッシングし、Stringでキーイングする。

ちょっとした注意:bitmap.getByteCount()を使用する場合は注意してください。

KITKATでは、このメソッドの結果を使用してビットマップのメモリ使用量を判断することができなくなりました。 getAllocationByteCount()を参照してください。

私はBitmapでLRUキャッシュを使用していました。 Application.onTrimMemory()をオーバーライドして、このメソッドが呼び出されるたびにキャッシュをクリアすれば十分だと思いました。

また、同じことをして、アプリケーションで利用できるヒープメモリの割合に基づいてキャッシュサイズを設定しました。

私のアプリがメモリ不足の状態で、メモリ不足の画像をダウンロードしようとすると、BitmapFactoryはまだBitmapのメモリを割り当てることができませんでした。ログにはonTrimMemory()メソッドがという非同期でと呼ばれていたことが示されました.がスローされた後でほぼ完全な秒数になることがありました。

はGOOGLE HEY:SYSTEMは、私は、OutOfMemoryErrorがスローされた後までメモリON LOW'M MEを伝えることができない場合はHELL AMで、私は私の記憶を管理することになってどのように?

狂気。シアー、まったくの狂気。

ここで私は最後に何をしたのですか:をキャッチ tryブロックにキャッシュをクリアしてから、サーバにイメージ要求を再試行します。彼らはあなたにしないと言う正確なこと。しかし、それは私の問題を解決した。アプリは今よりずっと安定しています。

LRUキャッシュを実装した後、アプリケーションのストレステストを行ってください。それを低メモリ状態にして、それがどのように動作するかを見てください。私にとっては、エミュレータを使うときにはうまくいきました。エミュレータは96Mの小さなヒープリミットを持っていましたが、画面解像度が高いと画像のリソースがかなり大きくなり、メモリを最大限に簡単に押し込めるようになりました。

あなたがサムネイルを表示しているが、あなたはサーバーから画像を取得しているし、彼らはあなたのImageViewよりも大きくなる可能性がある場合、あなたはこの記事読んで確認してください:メモリを無駄にすることなく、適切なサイズのビットマップをダウンロードする方法を学ぶためにLoading Large Bitmaps Efficiently | Android Developersを。

また、システムにキャッシングを行わせて、HttpResponseCacheを設定するだけでテストすることもできます。

あなたが何をしても、アプリケーションにストレスを与え、ヒープがあまり残っていないときの動作を確認してください。

少しの不満に対処する準備をしてください。

+0

こんにちは!現時点では、リストビューのコンストラクタでweakHashMapを初期化しています。そのマップにサムネイルを配置します。私はそれがLRUキャッシュを使う方が良いと思っていましたが、あなたの答えを読んだ後、少し怖いです。 – aeroxr1

+1

私はちょうど 'WeakHashMap'を見ました。私はそれがそのクラスで弱い参照を持つ*キー*であることを認識していませんでした。そのため、あなたは 'Map >'のようなマップを作りたいと思うかもしれません。私はまずこれをやったことを願っています。 'LruCache'クラスはGCに暗黙的な関係を持っていないので、かなり無駄です。だからあなたは正しい軌道に乗っているかもしれません。ただそれを試してみてください。もしうまく行けば、勝利を宣言して、それを1日と呼びましょう。 –

+0

弱いハッシュマップでは弱い参照を持つキーですか?本当に ?私はこれを知らなかった! – aeroxr1