8

以前に聞いたことがあると思いますが、それでもよくわからないことがあります。

私は2つの異なるアプローチを試しました:

  1. すべての画像をメモリに保持し、特定の制限を超え始めたら、それらの削除を開始します
  2. AndroidにSoftReferencesでこれを修正させます

2.では、それらをクリーンアップするだけで、2番目に割り当てることがあります。そして、私はあまり割り当てません-30-40画像50x50ピクセル。

だから私は1つに固執しています。問題は、制限は何ですか?

  1. デバイスから、ビットマップメモリ​​がどれだけ残っているかについての信頼できる情報を取得できますか?私はいくつかの調査を行い、DDMS値を監視しました。爆発するまで、(クリーンアップしない場合は)ますます多くのスペースを占有しています。残りわずか200Kの瞬間、次のシステムはさらに2Mを提供します...
  2. 現在、デバイスモデルまたは画面サイズに基づいて、ヒューリスティックな決定を使用しています。これは長期的には行き止まりだと思います。一部の電話ではメモリの例外が発生し、他の電話では完全に解放されました。
  3. 3番目の解決策はありますか?
4

5 に答える 5

8

最も重要な質問:recycle()ビットマップを作成していますか?これは、ジンジャーブレッド以前のアプリケーション(おそらくジンジャーブレッド後も)にとって非常に重要です。

Google I / O2011のAndroidアプリのメモリ管理セッションを見ると、Android向けの開発の特徴をよりよく理解することができました。

そのビデオでは、 MATと呼ばれるツール(メモリアナライザー)について説明しています。これは、リークされたオブジェクトがメモリ内にぶら下がっているかどうかを判断するのに役立ちます。おそらくあなたはあなたが持っていると思う30-40以上を持っているでしょう。

ヒープの現在のサイズなどを表示および/またはログに記録するには、Androidのメモリ不足の例外に関するこの回答のコードを使用することをお勧めします。

于 2011-08-10T21:31:28.127 に答える
4

画像のキャッシュは、私が作成してアプリストアに配置したアプリの重要な部分でした。アプリは、画像をダウンロードしてメモリとSDカードの両方にキャッシュし、その範囲が1回の実行を超えて拡張されるようにする必要があります。

一般的な考え方は、a)メタデータに基づくキーを介して画像を連想コンテナ(HashMap)に保存し、b)画像ファイルをSDCardに書き込むCachingManagerに画像を追加することでした。

メモリ不足の状態では、HashMapを解放します。それでも、画像はSD_Cardから取得して、もう一度メモリにキャッシュすることができます。

リサイクルせずにこれを行うことができましたが、それでもメモリの問題は見られません。私が理解しているように、リサイクルは必要ありませんが、ジンジャーブレッド以前の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);
        }
    }
}

//これがFile_ManagerクラスのwriteImage()の例です

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;
    }
}
于 2011-08-15T19:46:51.063 に答える
2

制限は、実行しているデバイスのVMヒープサイズに関連しています。これは、デバイスごと、OSごとに異なるため、16MB(アプリの合計)から256MB +(タブレットの場合)の範囲である可能性があります。

ローエンドの下に保持するか、デバイスごとに異なるビルドを作成するか、実行時にアプリに許容量を確認させ、それに応じてイメージをロードする必要があります。

ヒープ内の空き領域の量とそのサイズを確認する方法は次のとおりです。

このAPIrefは、利用可能なメソッドを支援します。

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

于 2011-07-29T16:04:43.823 に答える
0

高レベルの観点から、画像の読み込みとキャッシュはGreenDroidフレームワークの一部です。見てみな。

于 2011-08-15T16:31:04.550 に答える
-2

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

于 2011-08-15T23:16:05.730 に答える