11

私は現在、物語をたどるアプリを開発しています。ストーリーには、ImageViews を介して表示される複数の JPEG および PNG ファイルを含む「シーン」が含まれます。ImageView を作成し、次の関数を使用してレイアウトに追加します。

private ImageView newImage(Show show)
{
    ImageView iv = new ImageView(this);
    String filePath = comin.generateFilePath(show);
    Log.i(TAG, "newImage, filePath = " + filePath + " id = " + show.id);
    WeakReference<Bitmap> bmp = new WeakReference<Bitmap>(scaleBitmap(filePath)); //added 4/1/13
    //Bitmap bmp = scaleBitmap(filePath);
    Log.i(TAG, "newImage, width = " + bmp.get().getWidth() + ", height = " + bmp.get().getHeight());
    iv.setImageBitmap(bmp.get());
    iv.setScaleType(ImageView.ScaleType.FIT_XY);
    iv.setId(show.id);

    //set visibility
    if (show.visible)
        iv.setVisibility(View.VISIBLE);
    else
        iv.setVisibility(View.INVISIBLE);

    //set dimensions
    int width = (app.getWidth() * show.dimX) / 100;
    int height = (app.getHeight() * show.dimY) / 100;
    RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(width, height);
    iv.setLayoutParams(rlp);

    return iv;
}  

シーンが終了したら、画像がなく、タッチ イベントをリッスンするだけの ImageView を除いて、すべての ImageView をクリアします。

private void clearScene(boolean clearTouch)
{
    RelativeLayout parent = (RelativeLayout) findViewById(R.id.relative_layout);
    logMemory("clearScene, START");

    int count = parent.getChildCount();
    for (int a = count - 1; a >= 0; a--)
    {
        int id = parent.getChildAt(a).getId();
        String message = "clearScene id = " + id + ", count = " + count + ", a = " + a;
        if (id == TOUCH_VIEW_ID && !clearTouch)
        {
            message = message + ", ignore touch screen view";
        }
        else
        {
            unbindView(parent.getChildAt(a));
            parent.getChildAt(a).clearAnimation();
            parent.removeView(parent.getChildAt(a));
            message = message + ", unbindView, clearAnimation, removeView";
        }
        Log.i(TAG, message);
        logMemory("clearScene, CLEARED VIEW");
    }

    handler.removeCallbacksAndMessages(null);  //stop any future scheduled tasks from triggering
    logMemory("clearScene, BEFORE TRASH COLLECTOR");
    System.gc();
    logMemory("clearScene, AFTER TRASH COLLECTOR");
}

ご覧のとおり、unbindView() メソッドを呼び出して、あらゆる種類のメモリ リークの可能性を排除しようとしています。

private void unbindView(View view)
{
    String message = "unbindView, id = " + view.getId();
    try {view.setOnClickListener(null);} catch (Throwable mayHappen) {};
    try {view.setOnCreateContextMenuListener(null);} catch (Throwable mayHappen) {};
    try {view.setOnFocusChangeListener(null);} catch (Throwable mayHappen) {};
    try {view.setOnKeyListener(null);} catch (Throwable mayHappen) {};
    try {view.setOnLongClickListener(null);} catch (Throwable mayHappen) {};
    try {view.setOnClickListener(null);} catch (Throwable mayHappen) {};

    if (view.getBackground() != null)
    {
        message = message + ", setBackgroundCallback(null)";
        view.getBackground().setCallback(null);
    }

    if (view instanceof ImageView)
    {
        if (((ImageView)view).getDrawable() != null)
        {
            if (((ImageView)view).getDrawable() instanceof BitmapDrawable)
            {
                message = message + ", recycle bitmap";
                ((BitmapDrawable)((ImageView)view).getDrawable()).getBitmap().recycle();
            }
            message = message + ", setDrawableCallback(null)";
            ((ImageView)view).getDrawable().setCallback(null);
        }
        message = message + ", setImageBitmap(null), setBackgroundDrawable(null)";
        ((ImageView) view).setImageBitmap(null);
        ((ImageView) view).setBackgroundDrawable(null);
    }
    Log.i(TAG, message);
}

すべての ImageView の制限を解除したら、clearScene 関数でガベージ コレクターを実行します。

***編集 (4/2/13) OK、いくつかの調査と試行錯誤の後、メモリ ログを変更しました。関連するメソッドは次のとおりです。

onResume() では、Android のバージョンに応じてブール値を true に設定し (ビットマップにネイティブまたは Java メモリを使用するかどうかを判断するため)、古いメモリ値のデフォルト値を 0 に初期化します。

@Override
protected void onResume() 
{
    super.onResume();

    if (android.os.Build.VERSION.SDK_INT >= 11) debugJavaMemory = true;
    else debugNativeMemory = true;
    availableJavaMemoryOld = 0;
    availableNativeMemoryOld = 0;
    dialogDebug();
}  

これは私のロギング機能です。現在のバージョンの Android がネイティブまたは Java メモリを使用してビットマップを保存しているかどうかに応じてログに記録します。

private void logMemory(String callingFunction)
{
    if (debugJavaMemory)
    {
        long max = Runtime.getRuntime().maxMemory() / 1024;
        long used = Runtime.getRuntime().totalMemory() / 1024;
        long available = max - used;
        long change = available - availableJavaMemoryOld;
        if (availableJavaMemoryOld != 0)
            Log.i(TAG_MEMORY, "jMEM M:" + max + ", U:" + used + ", A:" + available + ", C:" + change + ", " + callingFunction);
        availableJavaMemoryOld = available;
    }
    else if (debugNativeMemory)
    {
        long max = Debug.getNativeHeapSize() / 1024;
        long used = Debug.getNativeHeapAllocatedSize() / 1024;
        long available = max - used;
        long change = available - availableNativeMemoryOld;
        if (availableNativeMemoryOld != 0)
            Log.i(TAG_MEMORY, "nMEM M:" + max + ", U:" + used + ", A:" + available + ", C:" + change + ", " + callingFunction);
        availableNativeMemoryOld = available;
    }
}  

Android 10 (2.3.3) を実行しているエミュレーターから収集したログを見ると、ガベージ コレクターが完全に機能しているように見えます。私が気付いた唯一の奇妙な点は、最大ネイティブ メモリが動的に増加する可能性があることでした!?

凡例: M: (最大メモリ)、U: (使用済みメモリ)、A: (使用可能メモリ)、C: (使用可能メモリの変化)、ログ関数を呼び出した関数

04-03 02:34:20.758: I/MEMORY(1045): nMEM M:18336, U:13287, A:5049, C:-2549, loadScene, ADDED IMAGE b:0, s:0, id:0
04-03 02:34:21.267: I/MEMORY(1045): nMEM M:21568, U:21391, A:177, C:-4872, loadScene, ADDED IMAGE b:0, s:0, id:1
04-03 02:34:35.227: I/MEMORY(1045): nMEM M:21568, U:13288, A:8280, C:8103, clearScene, CLEARED VIEW id:1
04-03 02:34:35.267: I/MEMORY(1045): nMEM M:21568, U:5184, A:16384, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:34:35.327: I/MEMORY(1045): nMEM M:21568, U:4977, A:16591, C:207, clearScene, AFTER TRASH COLLECTOR
04-03 02:34:36.067: I/MEMORY(1045): nMEM M:21568, U:13082, A:8486, C:-8105, loadScene, ADDED IMAGE b:1, s:0, id:0
04-03 02:34:47.177: I/MEMORY(1045): nMEM M:21568, U:4979, A:16589, C:8103, clearScene, CLEARED VIEW id:0
04-03 02:34:47.277: I/MEMORY(1045): nMEM M:21568, U:4978, A:16590, C:1, clearScene, AFTER TRASH COLLECTOR
04-03 02:34:47.997: I/MEMORY(1045): nMEM M:21568, U:13082, A:8486, C:-8104, loadScene, ADDED IMAGE b:1, s:1, id:0
04-03 02:34:49.307: I/MEMORY(1045): nMEM M:26224, U:21186, A:5038, C:-3448, loadScene, ADDED IMAGE b:1, s:1, id:1
04-03 02:34:50.597: I/MEMORY(1045): nMEM M:34328, U:29290, A:5038, C:0, loadScene, ADDED IMAGE b:1, s:1, id:2
04-03 02:34:51.839: I/MEMORY(1045): nMEM M:42432, U:37395, A:5037, C:-1, loadScene, ADDED IMAGE b:1, s:1, id:3
04-03 02:35:00.377: I/MEMORY(1045): nMEM M:42432, U:29293, A:13139, C:8102, clearScene, CLEARED VIEW id:3
04-03 02:35:00.387: I/MEMORY(1045): nMEM M:42432, U:21189, A:21243, C:8104, clearScene, CLEARED VIEW id:2
04-03 02:35:00.397: I/MEMORY(1045): nMEM M:42432, U:13085, A:29347, C:8104, clearScene, CLEARED VIEW id:1
04-03 02:35:00.407: I/MEMORY(1045): nMEM M:42432, U:4982, A:37450, C:8103, clearScene, CLEARED VIEW id:0
04-03 02:35:00.449: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:4, clearScene, AFTER TRASH COLLECTOR
04-03 02:35:01.217: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8105, loadScene, ADDED IMAGE b:1, s:2, id:0
04-03 02:35:23.458: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:35:23.508: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:1, clearScene, AFTER TRASH COLLECTOR
04-03 02:35:24.777: I/MEMORY(1045): nMEM M:42432, U:13082, A:29350, C:-8104, loadScene, ADDED IMAGE b:1, s:3, id:0
04-03 02:35:25.719: I/MEMORY(1045): nMEM M:42432, U:21186, A:21246, C:-8104, loadScene, ADDED IMAGE b:1, s:3, id:1
04-03 02:35:26.457: I/MEMORY(1045): nMEM M:42432, U:29291, A:13141, C:-8105, loadScene, ADDED IMAGE b:1, s:3, id:2
04-03 02:35:55.008: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:8104, clearScene, CLEARED VIEW id:2
04-03 02:35:55.027: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:8104, clearScene, CLEARED VIEW id:1
04-03 02:35:55.037: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:35:55.077: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:1, clearScene, AFTER TRASH COLLECTOR
04-03 02:35:55.829: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8105, loadScene, ADDED IMAGE b:1, s:4, id:0
04-03 02:35:56.427: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:-8104, loadScene, ADDED IMAGE b:1, s:4, id:1
04-03 02:36:00.257: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:8104, clearScene, CLEARED VIEW id:1
04-03 02:36:00.278: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:36:00.318: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:1, clearScene, AFTER TRASH COLLECTOR
04-03 02:36:01.687: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8105, loadScene, ADDED IMAGE b:1, s:5, id:0
04-03 02:36:06.437: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:36:06.487: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:1, clearScene, AFTER TRASH COLLECTOR
04-03 02:36:07.777: I/MEMORY(1045): nMEM M:42432, U:13082, A:29350, C:-8104, loadScene, ADDED IMAGE b:1, s:6, id:0
04-03 02:36:09.297: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:36:09.337: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:0, clearScene, AFTER TRASH COLLECTOR
04-03 02:36:10.727: I/MEMORY(1045): nMEM M:42432, U:13082, A:29350, C:-8104, loadScene, ADDED IMAGE b:1, s:7, id:0
04-03 02:36:20.947: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:36:20.987: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:0, clearScene, AFTER TRASH COLLECTOR
04-03 02:36:22.367: I/MEMORY(1045): nMEM M:42432, U:13082, A:29350, C:-8104, loadScene, ADDED IMAGE b:1, s:8, id:0
04-03 02:36:23.317: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:-8105, loadScene, ADDED IMAGE b:1, s:8, id:1
04-03 02:36:23.887: I/MEMORY(1045): nMEM M:42432, U:29291, A:13141, C:-8104, loadScene, ADDED IMAGE b:1, s:8, id:2
04-03 02:36:26.507: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:8104, clearScene, CLEARED VIEW id:2
04-03 02:36:26.517: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:8104, clearScene, CLEARED VIEW id:1
04-03 02:36:26.527: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:36:26.577: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:1, clearScene, AFTER TRASH COLLECTOR
04-03 02:36:27.797: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8105, loadScene, ADDED IMAGE b:1, s:9, id:0
04-03 02:36:29.248: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:36:29.287: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:1, clearScene, AFTER TRASH COLLECTOR
04-03 02:36:30.547: I/MEMORY(1045): nMEM M:42432, U:13082, A:29350, C:-8104, loadScene, ADDED IMAGE b:1, s:10, id:0
04-03 02:36:32.177: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:36:32.228: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:0, clearScene, AFTER TRASH COLLECTOR
04-03 02:36:33.467: I/MEMORY(1045): nMEM M:42432, U:13082, A:29350, C:-8104, loadScene, ADDED IMAGE b:1, s:11, id:0
04-03 02:36:33.977: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:-8105, loadScene, ADDED IMAGE b:1, s:11, id:1
04-03 02:36:34.527: I/MEMORY(1045): nMEM M:42432, U:29291, A:13141, C:-8104, loadScene, ADDED IMAGE b:1, s:11, id:2
04-03 02:36:35.058: I/MEMORY(1045): nMEM M:42432, U:37395, A:5037, C:-8104, loadScene, ADDED IMAGE b:1, s:11, id:3
04-03 02:36:41.260: I/MEMORY(1045): nMEM M:42432, U:29291, A:13141, C:8104, clearScene, CLEARED VIEW id:3
04-03 02:36:41.267: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:8104, clearScene, CLEARED VIEW id:2
04-03 02:36:41.278: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:8104, clearScene, CLEARED VIEW id:1
04-03 02:36:41.287: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:36:41.337: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:0, clearScene, AFTER TRASH COLLECTOR
04-03 02:36:42.618: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8104, loadScene, ADDED IMAGE b:2, s:0, id:0
04-03 02:37:00.550: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:37:00.587: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:0, clearScene, AFTER TRASH COLLECTOR
04-03 02:37:01.817: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8104, loadScene, ADDED IMAGE b:2, s:1, id:0
04-03 02:37:03.347: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:37:03.397: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:0, clearScene, AFTER TRASH COLLECTOR
04-03 02:37:04.607: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8104, loadScene, ADDED IMAGE b:2, s:2, id:0
04-03 02:37:05.258: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:-8104, loadScene, ADDED IMAGE b:2, s:2, id:1
04-03 02:37:07.677: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:8104, clearScene, CLEARED VIEW id:1
04-03 02:37:07.687: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:37:07.737: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:0, clearScene, AFTER TRASH COLLECTOR
04-03 02:37:09.017: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8104, loadScene, ADDED IMAGE b:2, s:3, id:0
04-03 02:37:10.327: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:-8104, loadScene, ADDED IMAGE b:2, s:3, id:1
04-03 02:37:13.330: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:8104, clearScene, CLEARED VIEW id:1
04-03 02:37:13.337: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:37:13.387: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:0, clearScene, AFTER TRASH COLLECTOR
04-03 02:37:14.697: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8104, loadScene, ADDED IMAGE b:2, s:4, id:0
04-03 02:37:16.037: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:-8104, loadScene, ADDED IMAGE b:2, s:4, id:1
04-03 02:37:17.367: I/MEMORY(1045): nMEM M:42432, U:29292, A:13140, C:-8105, loadScene, ADDED IMAGE b:2, s:4, id:2
04-03 02:37:19.087: I/MEMORY(1045): nMEM M:42432, U:37396, A:5036, C:-8104, loadScene, ADDED IMAGE b:2, s:4, id:3
04-03 02:37:44.347: I/MEMORY(1045): nMEM M:42432, U:29293, A:13139, C:8103, clearScene, CLEARED VIEW id:3
04-03 02:37:44.357: I/MEMORY(1045): nMEM M:42432, U:21189, A:21243, C:8104, clearScene, CLEARED VIEW id:2
04-03 02:37:44.367: I/MEMORY(1045): nMEM M:42432, U:13085, A:29347, C:8104, clearScene, CLEARED VIEW id:1
04-03 02:37:44.377: I/MEMORY(1045): nMEM M:42432, U:4981, A:37451, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:37:44.437: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:2, clearScene, AFTER TRASH COLLECTOR
04-03 02:37:45.667: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8104, loadScene, ADDED IMAGE b:2, s:5, id:0
04-03 02:37:46.917: I/MEMORY(1045): nMEM M:42432, U:21188, A:21244, C:-8105, loadScene, ADDED IMAGE b:2, s:5, id:1
04-03 02:37:48.167: I/MEMORY(1045): nMEM M:42432, U:29292, A:13140, C:-8104, loadScene, ADDED IMAGE b:2, s:5, id:2
04-03 02:37:49.807: I/MEMORY(1045): nMEM M:42432, U:37396, A:5036, C:-8104, loadScene, ADDED IMAGE b:2, s:5, id:3
04-03 02:38:08.239: I/MEMORY(1045): nMEM M:42432, U:29293, A:13139, C:8103, clearScene, CLEARED VIEW id:3
04-03 02:38:08.258: I/MEMORY(1045): nMEM M:42432, U:21189, A:21243, C:8104, clearScene, CLEARED VIEW id:2
04-03 02:38:08.267: I/MEMORY(1045): nMEM M:42432, U:13086, A:29346, C:8103, clearScene, CLEARED VIEW id:1
04-03 02:38:08.277: I/MEMORY(1045): nMEM M:42432, U:4982, A:37450, C:8104, clearScene, CLEARED VIEW id:0
04-03 02:38:08.317: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:3, clearScene, AFTER TRASH COLLECTOR
04-03 02:38:09.527: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8104, loadScene, ADDED IMAGE b:2, s:6, id:0  

前述のように、ImageView のバインドが解除された後、メモリは消去されます。

これは、Android 17 (4.2) を実行している壊れた Nexus 7 から収集したログです。ここでメモリがどのように使用されているかを理解するのは本当に難しいです。それは決して一貫していません!ImageView を読み込んだときにメモリが割り当てられないことがあります。新しい ImageView をロードしたときにのみメモリがクリアされることがあります。

凡例: M: (最大メモリ)、U: (使用済みメモリ)、A: (使用可能メモリ)、C: (使用可能メモリの変化)、ログ関数を呼び出した関数

04-02 22:37:05.866: I/MEMORY(15827): jMEM M:65536, U:21300, A:44236, C:0, loadScene, ADDED IMAGE b:0, s:0, id:0
04-02 22:37:06.136: I/MEMORY(15827): jMEM M:65536, U:29444, A:36092, C:-8144, loadScene, ADDED IMAGE b:0, s:0, id:1
04-02 22:37:19.806: I/MEMORY(15827): jMEM M:65536, U:29432, A:36104, C:12, clearScene, CLEARED VIEW id:1
04-02 22:37:19.806: I/MEMORY(15827): jMEM M:65536, U:29432, A:36104, C:0, clearScene, CLEARED VIEW id:0
04-02 22:37:19.836: I/MEMORY(15827): jMEM M:65536, U:29432, A:36104, C:0, clearScene, AFTER TRASH COLLECTOR
04-02 22:37:20.116: I/MEMORY(15827): jMEM M:65536, U:37536, A:28000, C:-8104, loadScene, ADDED IMAGE b:1, s:0, id:0
04-02 22:37:28.456: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:4, clearScene, CLEARED VIEW id:0
04-02 22:37:28.486: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, clearScene, AFTER TRASH COLLECTOR
04-02 22:37:28.756: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, loadScene, ADDED IMAGE b:1, s:1, id:0
04-02 22:37:29.226: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, loadScene, ADDED IMAGE b:1, s:1, id:1
04-02 22:37:29.706: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:-8104, loadScene, ADDED IMAGE b:1, s:1, id:2
04-02 22:37:30.156: I/MEMORY(15827): jMEM M:65536, U:53740, A:11796, C:-8104, loadScene, ADDED IMAGE b:1, s:1, id:3
04-02 22:37:38.676: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:8, clearScene, CLEARED VIEW id:3
04-02 22:37:38.676: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:0, clearScene, CLEARED VIEW id:2
04-02 22:37:38.676: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:0, clearScene, CLEARED VIEW id:1
04-02 22:37:38.676: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:0, clearScene, CLEARED VIEW id:0
04-02 22:37:38.696: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:0, clearScene, AFTER TRASH COLLECTOR
04-02 22:37:38.966: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:0, loadScene, ADDED IMAGE b:1, s:2, id:0
04-02 22:37:48.156: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:0, clearScene, CLEARED VIEW id:0
04-02 22:37:48.216: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:16200, clearScene, AFTER TRASH COLLECTOR
04-02 22:37:48.676: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, loadScene, ADDED IMAGE b:1, s:3, id:0
04-02 22:37:49.256: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, loadScene, ADDED IMAGE b:1, s:3, id:1
04-02 22:37:49.716: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:-8104, loadScene, ADDED IMAGE b:1, s:3, id:2
04-02 22:38:07.426: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:4, clearScene, CLEARED VIEW id:2
04-02 22:38:07.426: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:0, clearScene, CLEARED VIEW id:1
04-02 22:38:07.426: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:0, clearScene, CLEARED VIEW id:0
04-02 22:38:07.496: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:0, clearScene, AFTER TRASH COLLECTOR
04-02 22:38:07.766: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:0, loadScene, ADDED IMAGE b:1, s:4, id:0
04-02 22:38:08.096: I/MEMORY(15827): jMEM M:65536, U:53736, A:11800, C:-8104, loadScene, ADDED IMAGE b:1, s:4, id:1
04-02 22:38:10.896: I/MEMORY(15827): jMEM M:65536, U:53736, A:11800, C:0, clearScene, CLEARED VIEW id:1
04-02 22:38:10.896: I/MEMORY(15827): jMEM M:65536, U:53736, A:11800, C:0, clearScene, CLEARED VIEW id:0
04-02 22:38:10.916: I/MEMORY(15827): jMEM M:65536, U:53736, A:11800, C:0, clearScene, AFTER TRASH COLLECTOR
04-02 22:38:11.436: I/MEMORY(15827): jMEM M:65536, U:53736, A:11800, C:0, loadScene, ADDED IMAGE b:1, s:5, id:0
04-02 22:38:19.356: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:4, clearScene, CLEARED VIEW id:0
04-02 22:38:19.386: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:8100, clearScene, AFTER TRASH COLLECTOR
04-02 22:38:19.866: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:0, loadScene, ADDED IMAGE b:1, s:6, id:0
04-02 22:38:21.326: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:0, clearScene, CLEARED VIEW id:0
04-02 22:38:21.356: I/MEMORY(15827): jMEM M:65536, U:21300, A:44236, C:24332, clearScene, AFTER TRASH COLLECTOR
04-02 22:38:21.906: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:-8104, loadScene, ADDED IMAGE b:1, s:7, id:0
04-02 22:38:24.376: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:0, clearScene, CLEARED VIEW id:0
04-02 22:38:24.406: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:0, clearScene, AFTER TRASH COLLECTOR
04-02 22:38:24.916: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:0, loadScene, ADDED IMAGE b:1, s:8, id:0
04-02 22:38:25.496: I/MEMORY(15827): jMEM M:65536, U:37548, A:27988, C:-8144, loadScene, ADDED IMAGE b:1, s:8, id:1
04-02 22:38:25.796: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:-8104, loadScene, ADDED IMAGE b:1, s:8, id:2
04-02 22:38:28.356: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:0, clearScene, CLEARED VIEW id:2
04-02 22:38:28.356: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:0, clearScene, CLEARED VIEW id:1
04-02 22:38:28.356: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:0, clearScene, CLEARED VIEW id:0
04-02 22:38:28.376: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:0, clearScene, AFTER TRASH COLLECTOR
04-02 22:38:28.846: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:0, loadScene, ADDED IMAGE b:1, s:9, id:0
04-02 22:38:29.926: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:0, clearScene, CLEARED VIEW id:0
04-02 22:38:29.956: I/MEMORY(15827): jMEM M:65536, U:29400, A:36136, C:16252, clearScene, AFTER TRASH COLLECTOR
04-02 22:38:30.416: I/MEMORY(15827): jMEM M:65536, U:29400, A:36136, C:0, loadScene, ADDED IMAGE b:1, s:10, id:0
04-02 22:38:31.446: I/MEMORY(15827): jMEM M:65536, U:29400, A:36136, C:0, clearScene, CLEARED VIEW id:0
04-02 22:38:31.476: I/MEMORY(15827): jMEM M:65536, U:21300, A:44236, C:8100, clearScene, AFTER TRASH COLLECTOR
04-02 22:38:31.966: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:-8104, loadScene, ADDED IMAGE b:1, s:11, id:0
04-02 22:38:32.226: I/MEMORY(15827): jMEM M:65536, U:37548, A:27988, C:-8144, loadScene, ADDED IMAGE b:1, s:11, id:1
04-02 22:38:32.526: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:-8104, loadScene, ADDED IMAGE b:1, s:11, id:2
04-02 22:38:32.816: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:-8104, loadScene, ADDED IMAGE b:1, s:11, id:3
04-02 22:38:34.396: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:0, clearScene, CLEARED VIEW id:3
04-02 22:38:34.396: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:0, clearScene, CLEARED VIEW id:2
04-02 22:38:34.396: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:0, clearScene, CLEARED VIEW id:1
04-02 22:38:34.396: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:0, clearScene, CLEARED VIEW id:0
04-02 22:38:34.426: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:0, clearScene, AFTER TRASH COLLECTOR
04-02 22:38:34.886: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:0, loadScene, ADDED IMAGE b:2, s:0, id:0
04-02 22:38:35.776: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:0, clearScene, CLEARED VIEW id:0
04-02 22:38:35.816: I/MEMORY(15827): jMEM M:65536, U:21300, A:44236, C:32456, clearScene, AFTER TRASH COLLECTOR
04-02 22:38:36.256: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:-8104, loadScene, ADDED IMAGE b:2, s:1, id:0
04-02 22:38:36.976: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:0, clearScene, CLEARED VIEW id:0
04-02 22:38:37.006: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:0, clearScene, AFTER TRASH COLLECTOR
04-02 22:38:37.436: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:0, loadScene, ADDED IMAGE b:2, s:2, id:0
04-02 22:38:37.816: I/MEMORY(15827): jMEM M:65536, U:37548, A:27988, C:-8144, loadScene, ADDED IMAGE b:2, s:2, id:1
04-02 22:38:44.986: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:16, clearScene, CLEARED VIEW id:1
04-02 22:38:44.986: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, clearScene, CLEARED VIEW id:0
04-02 22:38:45.016: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, clearScene, AFTER TRASH COLLECTOR
04-02 22:38:45.496: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, loadScene, ADDED IMAGE b:2, s:3, id:0
04-02 22:38:45.996: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:-8104, loadScene, ADDED IMAGE b:2, s:3, id:1
04-02 22:38:48.306: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:0, clearScene, CLEARED VIEW id:1
04-02 22:38:48.306: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:0, clearScene, CLEARED VIEW id:0
04-02 22:38:48.336: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:0, clearScene, AFTER TRASH COLLECTOR
04-02 22:38:48.846: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:0, loadScene, ADDED IMAGE b:2, s:4, id:0
04-02 22:38:49.326: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:0, loadScene, ADDED IMAGE b:2, s:4, id:1
04-02 22:38:49.856: I/MEMORY(15827): jMEM M:65536, U:53740, A:11796, C:-8104, loadScene, ADDED IMAGE b:2, s:4, id:2
04-02 22:38:50.386: I/MEMORY(15827): jMEM M:65536, U:61844, A:3692, C:-8104, loadScene, ADDED IMAGE b:2, s:4, id:3
04-02 22:38:59.486: I/MEMORY(15827): jMEM M:65536, U:61832, A:3704, C:12, clearScene, CLEARED VIEW id:3
04-02 22:38:59.486: I/MEMORY(15827): jMEM M:65536, U:61832, A:3704, C:0, clearScene, CLEARED VIEW id:2
04-02 22:38:59.486: I/MEMORY(15827): jMEM M:65536, U:61832, A:3704, C:0, clearScene, CLEARED VIEW id:1
04-02 22:38:59.486: I/MEMORY(15827): jMEM M:65536, U:61832, A:3704, C:0, clearScene, CLEARED VIEW id:0
04-02 22:38:59.516: I/MEMORY(15827): jMEM M:65536, U:61832, A:3704, C:0, clearScene, AFTER TRASH COLLECTOR
04-02 22:38:59.936: I/MEMORY(15827): jMEM M:65536, U:61832, A:3704, C:0, loadScene, ADDED IMAGE b:2, s:5, id:0
04-02 22:39:00.356: I/MEMORY(15827): jMEM M:65536, U:61832, A:3704, C:0, loadScene, ADDED IMAGE b:2, s:5, id:1

http://developer.android.com/training/displaying-bitmaps/index.htmlで「ビットマップを効果的に表示する」トレーニングを受けました。

私はまた、次のstackoverflowの質問を経験してきました: ImageView
のビットマップ
ImageViewをリサイクルします: ImageViewが(ScrollView内で)表示されない場合、ビットマップを自動的にリサイクルしますAndroid
- ビットマップ作成時のメモリ不足例外
Bitmap decodeStream OutOfMemory Exception when ((freeMemory > bitmapSize) && (nativeFreeHeap < bitmap size)) Android 495KB の画像で 10MB のヒープ サイズを取得Android ImageView setImageBitmap Android メモリ リーク ソリューションAndroid カスタム ビュー ビットマップ メモリ リーク





そして、ウェブ全体でさらに多くの記事が掲載されています!

明確にするために、これは Nexus 7 でのみ発生するようです。エミュレータまたは Galaxy Nexus では問題は発生していません。これは、画像をスケーリングしていることが原因である可能性があると思います。

メモリリークがどこにあるかを検出するのを手伝ってください!

***編集 (2013 年 4 月 2 日) Android 10 (2.3.3) を実行しているエミュレーターからのログが、システムがメモリとガベージを割り当てていることを示している理由を特定するのを手伝ってください。 Android 17 (4.2) を実行している Nexus 7 は、システムがメモリを割り当て、ガベージ コレクタが明らかにランダムにメモリをクリアしていることを示していますか?

4

3 に答える 3

4

異なるプラットフォーム間でメモリの割り当てと収集が異なる理由を特定することはできませんでしたが、使用可能なメモリに収まるようにイメージを縮小することで、問題を軽減し、どのプラットフォームでもアプリケーションがクラッシュするのを防ぐことができました。

この最初の関数は、ビットマップ メモリが格納されている場所 (ネイティブまたは Java) を特定し、残りの使用可能なメモリ (KB 単位) を計算します。

private long calcAvailableMemory()
{
    long value = Runtime.getRuntime().maxMemory();
    String type = "";
    if (android.os.Build.VERSION.SDK_INT >= 11)
    {
        value = value / 1024) - (Runtime.getRuntime().totalMemory() / 1024);
        type = "JAVA";
    }
    else
    {
        value = value / 1024) - (Debug.getNativeHeapAllocatedSize() / 1024);
        type = "NATIVE";
    }
    Log.i(TAG, "calcAvailableMemory, size = " + value + ", type = " + type);
    return value;
}

この 2 番目の関数は、レイアウトにアタッチする ImageView を作成します。Show オブジェクトには、サイズやファイルパスなど、ImageView を初期化するために必要なさまざまな変数が含まれています。長い maxImageMemory は最初の関数から派生し、レイアウトにアタッチしているビューの数で割って最大量を求めます。各ビットマップを割り当てるメモリの。

private ImageView newImage(Show show, long maxImageMemory)
{
    ImageView iv = new ImageView(this);
    String filePath = comin.generateFilePath(show);
    Bitmap bmp = scaleBitmap(filePath, maxImageMemory);
    Log.i(TAG, "newImage, id:" + show.id + ", file:" + filePath + ", x:" + bmp.getWidth() + ", y:" + bmp.getHeight());
    iv.setImageBitmap(bmp);
    iv.setScaleType(ImageView.ScaleType.FIT_XY);
    iv.setId(show.id);

    //set visibility
    if (show.visible)
        iv.setVisibility(View.VISIBLE);
    else
        iv.setVisibility(View.INVISIBLE);

    //set dimensions
    int width = (app.getWidth() * show.dimX) / 100;
    int height = (app.getHeight() * show.dimY) / 100;
    RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(width, height);
    iv.setLayoutParams(rlp);

    return iv;
}  

この 3 番目の関数は、関数 2 で作成された ImageView に読み込まれるビットマップをスケーリングします。while ループは重要な部分であり、ビットマップに必要なメモリが使用可能な最大メモリより小さくなるまでサンプル サイズを増やします。

private Bitmap scaleBitmap(String path, long maxImageMemory)
{
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(path, options);

    int sample = 1;
    //Scale image to screen resolution
    if (options.outHeight > app.getHeight() || options.outWidth > app.getWidth())
    {
        int heightRatio = Math.round((float) options.outHeight / (float) app.getHeight());
        int widthRatio = Math.round((float) options.outWidth / (float) app.getWidth());
        sample = heightRatio < widthRatio ? heightRatio : widthRatio;
    }

    //Scale image to stay within memory limitations
    while (calcBitmapSize(options.outWidth, options.outHeight, sample) > maxImageMemory)
    {
        sample++;
    }

    options.inSampleSize = sample;
    options.inPurgeable = true;
    options.inInputShareable = true;
    options.inJustDecodeBounds = false;

    Log.i(TAG, "scaleBitmap, scaleSample = " + sample);
    return BitmapFactory.decodeFile(path, options);
}  

この 4 番目の関数は、元の解像度と提案されたサンプル サイズに応じて、ビットマップに必要なメモリ量を計算します。

private long calcBitmapSize(int width, int height, int sample)
{
    long value = ((width/sample) * (height/sample) * 4) / 1024;
    Log.i(TAG, "calcBitmapSize, size = " + value);
    return value;
}  

最後に、これらすべてのメモリの問題のトラブルシューティングを支援するために、この関数を開発しました。実行している Android のバージョンに応じてメモリ使用率を記録します。

private void logMemory(String callingFunction)
{
    long max = Runtime.getRuntime().maxMemory() / 1024;

    if (debugJavaMemory)
    {
        long used = Runtime.getRuntime().totalMemory() / 1024;
        long available = max - used;
        long change = available - availableJavaMemoryOld;
        if (availableJavaMemoryOld != 0)
            Log.i(TAG_MEMORY, "jMEM M:" + max + ", U:" + used + ", A:" + available + ", C:" + change + ", " + callingFunction);
        availableJavaMemoryOld = available;
    }
    else if (debugNativeMemory)
    {
        long used = Debug.getNativeHeapAllocatedSize() / 1024;
        long available = max - used;
        long change = available - availableNativeMemoryOld;
        if (availableNativeMemoryOld != 0)
            Log.i(TAG_MEMORY, "nMEM M:" + max + ", U:" + used + ", A:" + available + ", C:" + change + ", " + callingFunction);
        availableNativeMemoryOld = available;
    }
}
于 2013-04-03T15:28:12.883 に答える
1

数か月前にこの問題が発生しました。これを試してください。役立つ場合があります。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap bitmap = BitmapFactory.decodeStream(fis, null, options);
于 2013-04-02T13:20:30.903 に答える
0

このリンクが役立つ場合がありますhttp://developer.android.com/training/displaying-bitmaps/load-bitmap.htmlこの問題は、720x1280 の大型モバイルのdrawable-xhdpiフォルダーでドローアブル が使用できない場合にも発生します。使用しているドローアブルが正しいドローアブル フォルダーにあることを確認してください。

于 2013-04-02T13:44:22.007 に答える