Android学習ノート_78_ Android開発ではソフトリファレンスと弱リファレンスでメモリオーバーフロー防止

5188 ワード

 《Effective Java 2nd Edition》 , 6 “         ”  ,  Java        ,            ,            ,      、                     。         WeakHashMap                  。            ,       “   ”     ,         。    《Java      :           》           Map                ,       hprof         ,                   ,    WeakHashMap     ,       。                      ,          ,          。

    1、    

     JDK1.2    ,            ,                    。            :   、   、       。

       :           :Object object=new Object(); object        。           ,              ,           。        ,Java       OutOfMemoryError  ,       ,                         。

       (SoftReference):            ,              。        ,           ,          ,           。            ,           。                 。             (ReferenceQueue)    ,                ,Java                         。

       (WeakReference):            ,              。            :                    。                        ,              ,            ,        。  ,                  ,                      。              (ReferenceQueue)    ,                ,Java                         。

       (PhantomReference):“   ”    ,      ,          ,               。             ,             ,             。                    。                  :           (ReferenceQueue)    。               ,          ,            ,                    。                       ,                  。                      ,                           。

以下では、ソフトリファレンスの使用を例に詳細に説明します.弱いリファレンスの使用方法はソフトリファレンスと似ています.
私たちのアプリケーションでは、デフォルトのアイコン、デフォルトのゲームアイコンなど、多くのデフォルトの画像が使用されるとします.画像を毎回読み込むと、ファイルの読み取りにハードウェア操作が必要なため、速度が遅くなり、パフォーマンスが低下します.そこで,画像をキャッシュし,必要に応じてメモリから直接読み出すことを考えた.しかし、画像のメモリ容量が大きいため、多くの画像をキャッシュするのに多くのメモリが必要となり、OutOfMemory異常が発生しやすい可能性があります.この場合,この問題を回避するためにソフトリファレンス技術を用いることを考えることができる.
まずHashMapを定義し、ソフトリファレンスオブジェクトを保存します.
private Map> imageCache = new HashMap>();
 
BitmapのソフトリファレンスをHashMapに保存する方法を定義します.
    public void addBitmapToCache(String path) {
       //強参照Bitmapオブジェクト
        Bitmap bitmap = BitmapFactory.decodeFile(path);
       //ソフトリファレンスBitmapオブジェクト
        SoftReference softBitmap = new SoftReference(bitmap);
       //オブジェクトをMapに追加してキャッシュします
        imageCache.put(path, softBitmap);
    }
 
 
    取得時には、SoftReferenceのget()メソッドでBitmapオブジェクトを得ることができます.
    public Bitmap getBitmapByPath(String path) {
       //ソフトリファレンスのBitmapオブジェクトをキャッシュから取り出す
        SoftReference softBitmap = imageCache.get(path);
       //ソフトリファレンスが存在するかどうかを判断する
        if (softBitmap == null) {
            return null;
        }
       //Bitmapオブジェクトを取り出し、メモリ不足でBitmapが回収されると空になります
        Bitmap bitmap = softBitmap.get();
        return bitmap;
    }
 
ソフトリファレンスを使用すると、OutOfMemory異常が発生する前に、これらのキャッシュされたピクチャリソースのメモリ領域を解放することができ、メモリが上限に達しないようにし、Crashの発生を避けることができます.
なお、このJavaオブジェクトをゴミ回収器で回収する前に、SoftReferenceクラスが提供するgetメソッドはJavaオブジェクトの強い参照を返し、ゴミスレッドがJavaオブジェクトを回収するとgetメソッドはnullを返します.したがって、ソフト参照オブジェクトを取得するコードでは、Nullであるか否かを判断し、Null PointerException異常が発生してアプリケーションがクラッシュしないようにしなければなりません.
 
経験の共有:
いったいいつソフトリファレンスを使うのか、いつ弱リファレンスを使うのか.
個人的には、OutOfMemoryの異常を回避したいだけならソフトリファレンスを使用できると思います.アプリケーションの性能が気になる場合は、メモリを消費している比較的大きなオブジェクトをできるだけ早く回収したい場合は、弱リファレンスを使用できます.
また、オブジェクトが頻繁に使用されているかどうかによって判断できます.オブジェクトが頻繁に使用される可能性がある場合は、できるだけソフトリファレンスを使用します.オブジェクトが使用されない可能性が高い場合は、弱いリファレンスを使用することができます.
また、弱引用機能と同様にWeakHashMapである.WeakHashMapは所与のキーに対してそのマッピングの存在はゴミ回収器によるこのキーの回収を阻止せず、回収後、そのエントリはマッピングから効率的に除去される.WeakHashMapはReferenceQueueを用いて実現される.
 
Map<String, SoftReference<Bitmap>> iconCache=new HashMap<String, SoftReference<Bitmap>>();

if (iconCache.containsKey(iconname)) {

SoftReference<Bitmap> softref = iconCache.get(iconname);

if (softref != null) {

   Bitmap bitmap = softref.get();

   if (bitmap != null) {

       iv_book.setImageBitmap(bitmap);

   } else {

       loadimage(iv_book, book, iconname);

   }



}



} else {

    loadimage(iv_book, book, iconname);

}







iconCache.put(iconname,new SoftReference<Bitmap>(bitmap));