2011-07-29 5 views
8

私はそれが以前に尋ねられ、尋ねられていると思うが、まだ理解できないことがある。Androidイメージのキャッシュ - 方法

私は2つの異なるアプローチしようとしている:SoftReferencesとアンドロイド修正してみましょう、これを一定の限度を超えることが開始されたときに、メモリ内のすべての画像を保管してください彼らに

  • の除去開始

    2.それはちょうどときどき私はそれらを割り当てる秒を掃除している!私はあまりにも多くの - 30-40イメージ50x50ピクセルを割り当てません。

    私は1つに固執しています。問題は限界です。

    1. 正確なビットマップメモリ​​が残っているかどうか、デバイスから信頼できる情報を得ることはできますか?私はいくつかの研究を行い、DDMSの値を見ています。爆発するまでには、それだけスペースを取っています(私がクリーンアップしなければ)。 1つの瞬間に200Kしか残っていません。次にシステムは2Mを提供します。
    2. 現在、デバイスモデルまたは画面サイズに基づいてヒューリスティックな決定を使用しています。私はこれが長期的にはデッドエンドだと思う。一部の電話機ではメモリ例外が発生し、他の電話機では完全に無料となります。
    3. 3つ目の解決策がありますか?
  • +0

    30-40の画像サイズ50x50は、OOMEを引き起こしません。 おそらく大きなものをロードしますか?そうであれば、それらを縮小することができます。 また、一部の画像がSoftReferenceから消去される場合、それらは使用されていないので、必要に応じて再ロードしてください。 –

    答えて

    8

    ほとんどの重要な質問は:ですあなたrecycle() - あなたのビットマップ?これは、前のジンジャーブレッドのアプリケーション(おそらくポストジンジャーブレッド)でも非常に重要です。

    Memory Management for Android Apps session from Google I/O 2011を見ると、Android用の開発の特質をより深く理解するのに役立ちました。 Memory Analyzer - - あなたがリークされているメモリにぶらぶらオブジェクトを持っているかどうかを判断するのに便利ですビデオはMATと呼ばれるツールに言及していること

    。おそらく、あなたはあなたが持っていると思う30-40以上のものがあります。

    ヒープの現在のサイズなどを表示および/または記録するには、this answer about Android Out of Memory exceptionsのコードを使用することをおすすめします。

    +0

    リンクありがとうございました。私はそれらをリサイクルしようとしましたが、彼らはいくつかのビューで使用され、彼らは彼らが使用されている活動に戻るときにクラッシュを引き起こします。 – Danail

    2

    これは、デバイスとOSとOSが異なるため、制限はドライブ上のVMヒープサイズに関連しています。これは16MB(アプリケーションの合計)から256MB +(タブレット)。

    あなたは下端の下に置いておくか、デバイスごとに異なるビルドを作成するか、実行時にアプリケーションがそれに応じて画像をロードするようにする必要があります。

    ヒープ内の空き領域の量と、それの大きさをチェックするための方法があります。

    このAPI refはavilable方法をお届けします。

    http://developer.android.com/reference/android/app/ActivityManager.html#getMemoryClass

    +0

    Hmm。私はそこで何を使用するのですか? MemoryInfo?それは私にやや拘束されているように見えますし、ネイティブヒープについてですか?または通常のヒープですか?私はこれまでDebug.getNativeHeapFreeSize()を使用していましたが、信頼性がありません - アプリケーションがより多くのビットマップメモリ​​を必要とする場合、TEMPORARY最大限のサイズを与えます。 – Danail

    +0

    NDKを使用してネイティブに明示的に割り当てる場合を除き、ネイティブヒープ情報を使用したくないです。 Java VMはヒープサイズを提供しますが、ヒープサイズの一部はビットマップなどの特定のファクトリコールによってネイティブに割り当てられます。これはネイティブであるにもかかわらず、割り当てられたVMヒープサイズから差し引かれます。したがって、VMヒープが16の場合は、ネイティブに4MBを割り当てて、残りの12個をVMヒープに配置します。 getMemoryClass()およびgetLargeMemoryClass()は、実行中のデバイスが許可するVMヒープ "クラス"を提供します。これはあなたのアプリが割り当てることが許可される最大値です。 – Hamid

    0

    高レベルの観点から、イメージの読み込みとキャッシングはGreenDroid frameworkの一部です。見てみな。

    4

    イメージキャッシュは、私が構築してアプリストアに入れたアプリの重要な部分でした。アプリケーションは、画像をダウンロードしてメモリとSDCardの両方にキャッシュする必要があり、スコープは1回の実行を超えて拡張されます。

    一般的な考え方は、(a)画像を関連コンテナ(HashMap)にメタデータに基づくキーを介して格納し、b)画像ファイルをSDカード。

    メモリが不足している間は、HashMapを解放します。それでもなお、SD_Cardからイメージを取得し、再びメモリにキャッシュすることができます。

    私はこれをリサイクルせずに行うことができましたが、メモリの問題はありません。私が理解しているように、リサイクルは必要ありませんが、ビットマップ用のビットマップの割り当ては、Gingerbread以前のOSでネイティブメモリを使用しているため、「ビットマップ」に使用されていたメモリの初期リリースを取得するのに役立ちます。つまり、Dalvikヒープの一部ではないメモリです。したがって、ガベージコレクタはこのメモリを解放せず、実装固有のポリシーによって解放されます。

    これは、CACHE_MANAGERクラスからである。ここでは

    public static synchronized void addImage(Bitmap b, String urlString, boolean bSaveToFile, IMAGE_TYPES eIT, boolean bForce) 
    { 
        String szKey = getKeyFromUrlString(urlString, eIT); 
    
        if (false == m_hmCachedImages.containsKey(szKey) || bForce) 
        { 
         m_hmCachedImages.put(szKey, b); 
         if (bSaveToFile) 
         { 
          boolean bIsNull = false; 
          // Write a null object to disk to prevent future query for non-existent image. 
          if (null == b) 
          { 
           try 
           { 
            bIsNull = true; 
            b = getNullArt(); 
           } 
           catch (NullPointerException e) 
           { 
            e.printStackTrace(); 
            throw e; 
           } 
          } 
    
          // Don't force null art to disk 
          if (false == File_Manager.imageExists(szKey) || (bForce && bIsNull == false)) 
           File_Manager.writeImage(b, szKey); 
         } 
        } 
    } 
    

    // writeImageの例()File_Managerクラスから

    public static void writeImage(Bitmap bmp, String szFileName) 
    { 
        checkStorage(); 
    
        if (false == mExternalStorageWriteable) 
        { 
         Log.e("FileMan", "No Writable External Device Available"); 
         return; 
        } 
    
        try 
        { 
         // Create dirctory if doesn't exist 
         String szFilePath = getFilesPath(); 
         boolean exists = (new File(szFilePath)).exists(); 
         if (!exists) 
         { 
          new File(szFilePath).mkdirs(); 
         } 
    
         // Create file 
         File file = new File(szFilePath, szFileName); 
    
         // Write to file 
         FileOutputStream os = new FileOutputStream(file); 
         bmp.compress(Bitmap.CompressFormat.PNG, 90, os); 
        } catch (IOException e) 
        { 
         // Unable to create file, likely because 
         // external storage is 
         // not currently mounted. 
         Log.e("FileMan", "Error writing file", e); 
        } catch (Exception e) 
        { 
         e.printStackTrace(); 
         throw e; 
        } 
    } 
    
    +0

    私との状況はほぼ同じです、 。もちろん、メモリリークが発生する可能性があります。 – Danail

    -2

    あなたはそれがキャッシュしている、画像を表示するためにWebViewを使用することができます内蔵されています。さらに、特別なコードなしで、2本指のズームやスクロールをサポートしています。

    関連する問題