4

パン/ズーム機能を使用して、SDCARD から画像を表示する小さなウィジェットを作成しようとしています。ほとんどの画像が完全にサンプリングされたビットマップとしてメモリに収まらないことに気付いた後、もう少し複雑なことを試しています。高速なパンとズームのために画像全体のダウンサンプリングされたビットマップを作成し、高解像度のトリミングを行います。バックグラウンドで計算され、完了時に低解像度で描画される、ビューポートに表示されているものの画像の部分 (別のスレッド)。

検索の割り当ての後、プロセスでメモリ例外なしで、画像の一部をロードできる素晴らしい BitmapRegionDecoder を最終的に見つけました。

うふふ、そうでしょ?

ただ...多くの画像を切り替えている間-私は、BitmapRegionDecoderがrecycle()の呼び出し後に使用しているメモリを実際に解放していないことを発見しました...ヒープは、イライラするアウトオブ-メモリー...

問題を示す小さなループを次に示します。

new AsyncTask<String, Integer, Void>() {
    BitmapRegionDecoder decoder;

    @Override
    protected Void doInBackground(String... params) {

        for (int i=0; i<30;i++){
            try {
                // get a decoder instance
                decoder = BitmapRegionDecoder.newInstance(params[0], false);

                // (I'm not even doing anything with it!)

                // recycle, null-it, g-collect it, just die already:
                decoder.recycle();
                decoder=null;
                System.gc();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }

            //print the memory usage after each step:
            onProgressUpdate(i);
        }

        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);

        //just print the heap sizes
        Double allocated = Double.valueOf(Debug.getNativeHeapAllocatedSize())/Double.valueOf((1048576));
        Double available = Double.valueOf(Debug.getNativeHeapSize())/1048576.0;
        Double free = Double.valueOf(Debug.getNativeHeapFreeSize())/1048576.0;
        DecimalFormat df = new DecimalFormat();
        df.setMaximumFractionDigits(2);
        df.setMinimumFractionDigits(2);

        Log.d("MEM", Integer.toString(values[0]) + " - alloc " + df.format(allocated) + "MB of " + df.format(available) + "MB (" + df.format(free) + "MB free)");

    }

}.execute(SOME_LARGE_IMAGE_PATH);

SOME_LARGE_IMAGE_PATH は 3000x3000 の PNG ファイルです (カメラでキャプチャされた画像からそれほど離れていません)。

API-10 を使用してエミュレーターで実行しました。

以下は、MEM TAG のみでフィルタリングされた LogCat です。

 0 - alloc 11.44MB of 18.95MB (0.09MB free)
 1 - alloc 18.40MB of 25.98MB (0.10MB free)
 2 - alloc 25.38MB of 32.96MB (0.10MB free)
 3 - alloc 32.36MB of 39.94MB (0.10MB free)
 4 - alloc 39.35MB of 46.92MB (0.10MB free)
 5 - alloc 46.33MB of 53.90MB (0.10MB free)
 6 - alloc 53.31MB of 60.88MB (0.10MB free)
 7 - alloc 60.30MB of 67.87MB (0.10MB free)
 8 - alloc 67.28MB of 74.85MB (0.09MB free)
 9 - alloc 74.26MB of 81.83MB (0.09MB free)
 10 - alloc 81.24MB of 88.81MB (0.09MB free)
 11 - alloc 88.23MB of 95.79MB (0.09MB free)
 12 - alloc 95.21MB of 102.78MB (0.09MB free)
 13 - alloc 102.19MB of 109.76MB (0.09MB free)
 14 - alloc 109.17MB of 116.74MB (0.09MB free)
 15 - alloc 116.16MB of 123.72MB (0.09MB free)
 16 - alloc 123.14MB of 130.70MB (0.09MB free)
 17 - alloc 130.12MB of 137.69MB (0.09MB free)
 18 - alloc 137.11MB of 144.67MB (0.09MB free)
 19 - alloc 144.09MB of 151.65MB (0.09MB free)
 20 - alloc 151.07MB of 158.63MB (0.09MB free)
 21 - alloc 158.05MB of 165.61MB (0.10MB free)
 22 - alloc 165.04MB of 172.61MB (0.09MB free)
 23 - alloc 172.02MB of 179.59MB (0.09MB free)
 24 - alloc 179.00MB of 186.57MB (0.09MB free)
 25 - alloc 185.45MB of 193.55MB (0.16MB free)
 26 - alloc 192.44MB of 200.07MB (0.16MB free)

そして、それはクラッシュしました....

および完全な LogCat:

 0 - alloc 11.44MB of 18.95MB (0.09MB free)
 GC_EXPLICIT freed 37K, 51% free 2644K/5379K, external 2043K/2137K, paused 47ms
 1 - alloc 18.40MB of 25.98MB (0.10MB free)
 GC_EXPLICIT freed 41K, 51% free 2637K/5379K, external 2043K/2137K, paused 55ms
 2 - alloc 25.38MB of 32.96MB (0.10MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 46ms
 3 - alloc 32.36MB of 39.94MB (0.10MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 54ms
 4 - alloc 39.35MB of 46.92MB (0.10MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 48ms
 5 - alloc 46.33MB of 53.90MB (0.10MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 59ms
 6 - alloc 53.31MB of 60.88MB (0.10MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 47ms
 7 - alloc 60.30MB of 67.87MB (0.10MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 54ms
 8 - alloc 67.28MB of 74.85MB (0.09MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 66ms
 9 - alloc 74.26MB of 81.83MB (0.09MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 91ms
 10 - alloc 81.24MB of 88.81MB (0.09MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 75ms
 11 - alloc 88.23MB of 95.79MB (0.09MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 56ms
 12 - alloc 95.21MB of 102.78MB (0.09MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 46ms
 13 - alloc 102.19MB of 109.76MB (0.09MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 53ms
 14 - alloc 109.17MB of 116.74MB (0.09MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 57ms
 15 - alloc 116.16MB of 123.72MB (0.09MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 61ms
 16 - alloc 123.14MB of 130.70MB (0.09MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 47ms
 17 - alloc 130.12MB of 137.69MB (0.09MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 56ms
 18 - alloc 137.11MB of 144.67MB (0.09MB free)
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 56ms
 19 - alloc 144.09MB of 151.65MB (0.09MB free)
 Process com.android.settings (pid 166) has died.
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 58ms
 20 - alloc 151.07MB of 158.63MB (0.09MB free)
 Process com.android.deskclock (pid 262) has died.
 Process com.android.music (pid 204) has died.
 Process com.yakstudio.moody (pid 287) has died.
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 52ms
 21 - alloc 158.05MB of 165.61MB (0.10MB free)
 Process com.android.email (pid 275) has died.
 Process android.process.media (pid 231) has died.
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 55ms
 22 - alloc 165.04MB of 172.61MB (0.09MB free)
 Process com.android.defcontainer (pid 427) has died.
 Process com.svox.pico (pid 440) has died.
 Process com.android.quicksearchbox (pid 218) has died.
 Low Memory: No more background processes.
 purging 38K from font cache [5 entries]
 GC_EXPLICIT freed 125K, 51% free 2771K/5639K, external 2168K/2674K, paused 107ms
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 46ms
 23 - alloc 172.02MB of 179.59MB (0.09MB free)
 Process com.android.launcher (pid 150) has died.
 Low Memory: No more background processes.
 WIN DEATH: Window{40735be0 com.android.launcher/com.android.launcher2.Launcher paused=false}
 purging 6K from font cache [1 entries]
 GC_EXPLICIT freed 183K, 50% free 2925K/5767K, external 1625K/2137K, paused 113ms
 GC_EXPLICIT freed 33K, 51% free 2637K/5379K, external 2043K/2137K, paused 60ms
 24 - alloc 179.00MB of 186.57MB (0.09MB free)
 purging 67K from font cache [6 entries]
 GC_EXPLICIT freed 1K, 51% free 2669K/5379K, external 2043K/2137K, paused 83ms
 purging 141K from font cache [14 entries]
 GC_EXPLICIT freed 230K, 49% free 4217K/8263K, external 3125K/3903K, paused 190ms
 GC_EXPLICIT freed 69K, 52% free 2600K/5379K, external 1645K/2137K, paused 67ms
 25 - alloc 185.45MB of 193.55MB (0.16MB free)
 Process jp.co.omronsoft.openwnn (pid 124) has died.
 Scheduling restart of crashed service jp.co.omronsoft.openwnn/.OpenWnnJAJP in 5000ms
 Low Memory: No more background processes.
 Session failed to close due to remote exception
 android.os.DeadObjectException
    at android.os.BinderProxy.transact(Native Method)
    at com.android.internal.view.IInputMethodSession$Stub$Proxy.finishSession(IInputMethodSession.java:346)
    at com.android.server.InputMethodManagerService.finishSession(InputMethodManagerService.java:896)
    at com.android.server.InputMethodManagerService.clearCurMethodLocked(InputMethodManagerService.java:907)
    at com.android.server.InputMethodManagerService.onServiceDisconnected(InputMethodManagerService.java:924)
    at android.app.LoadedApk$ServiceDispatcher.doDeath(LoadedApk.java:1069)
    at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1083)
    at android.os.Handler.handleCallback(Handler.java:587)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:123)
    at com.android.server.ServerThread.run(SystemServer.java:540)
 Session failed to close due to remote exception
 android.os.DeadObjectException
    at android.os.BinderProxy.transact(Native Method)
    at com.android.internal.view.IInputMethodSession$Stub$Proxy.finishSession(IInputMethodSession.java:346)
    at com.android.server.InputMethodManagerService.finishSession(InputMethodManagerService.java:896)
    at com.android.server.InputMethodManagerService.clearCurMethodLocked(InputMethodManagerService.java:911)
    at com.android.server.InputMethodManagerService.onServiceDisconnected(InputMethodManagerService.java:924)
    at android.app.LoadedApk$ServiceDispatcher.doDeath(LoadedApk.java:1069)
    at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1083)
    at android.os.Handler.handleCallback(Handler.java:587)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:123)
    at com.android.server.ServerThread.run(SystemServer.java:540)
 Start proc jp.co.omronsoft.openwnn for service jp.co.omronsoft.openwnn/.OpenWnnJAJP: pid=723 uid=10004 gids={}
 GC_EXPLICIT freed 10K, 53% free 2538K/5379K, external 1625K/2137K, paused 201ms
 GC_EXPLICIT freed <1K, 53% free 2538K/5379K, external 1625K/2137K, paused 228ms
 GC_EXPLICIT freed <1K, 53% free 2538K/5379K, external 1625K/2137K, paused 158ms
 No JNI_OnLoad found in /system/lib/libwnndict.so 0x40515658, skipping init
 GC_CONCURRENT freed 1052K, 55% free 3079K/6727K, external 1625K/2137K, paused 9ms+8ms
 Ignoring onBind: cur seq=12, given seq=15
 GC_EXPLICIT freed 34K, 52% free 2600K/5379K, external 1645K/2137K, paused 92ms
 26 - alloc 192.44MB of 200.07MB (0.16MB free)
 Process jp.co.omronsoft.openwnn (pid 723) has died.
 Scheduling restart of crashed service jp.co.omronsoft.openwnn/.OpenWnnJAJP in 20000ms
 Low Memory: No more background processes.
 Session failed to close due to remote exception
 android.os.DeadObjectException
    at android.os.BinderProxy.transact(Native Method)
    at com.android.internal.view.IInputMethodSession$Stub$Proxy.finishSession(IInputMethodSession.java:346)
    at com.android.server.InputMethodManagerService.finishSession(InputMethodManagerService.java:896)
    at com.android.server.InputMethodManagerService.clearCurMethodLocked(InputMethodManagerService.java:907)
    at com.android.server.InputMethodManagerService.onServiceDisconnected(InputMethodManagerService.java:924)
    at android.app.LoadedApk$ServiceDispatcher.doDeath(LoadedApk.java:1069)
    at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1083)
    at android.os.Handler.handleCallback(Handler.java:587)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:123)
    at com.android.server.ServerThread.run(SystemServer.java:540)
 Session failed to close due to remote exception
 android.os.DeadObjectException
    at android.os.BinderProxy.transact(Native Method)
    at com.android.internal.view.IInputMethodSession$Stub$Proxy.finishSession(IInputMethodSession.java:346)
    at com.android.server.InputMethodManagerService.finishSession(InputMethodManagerService.java:896)
    at com.android.server.InputMethodManagerService.clearCurMethodLocked(InputMethodManagerService.java:911)
    at com.android.server.InputMethodManagerService.onServiceDisconnected(InputMethodManagerService.java:924)
    at android.app.LoadedApk$ServiceDispatcher.doDeath(LoadedApk.java:1069)
    at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1083)
    at android.os.Handler.handleCallback(Handler.java:587)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:123)
    at com.android.server.ServerThread.run(SystemServer.java:540)
 Process com.ykstudio.ykLibDemo (pid 626) has died.
 WIN DEATH: Window{4069b908 com.ykstudio.ykLibDemo/com.ykstudio.ykLibDemo.MainActivity paused=false}
 channel '406fd480 com.ykstudio.ykLibDemo/com.ykstudio.ykLibDemo.SuperImageViewActivity (server)' ~ Consumer closed input channel or an error occurred.  events=0x8
 channel '406fd480 com.ykstudio.ykLibDemo/com.ykstudio.ykLibDemo.SuperImageViewActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
 WIN DEATH: Window{406fd480 com.ykstudio.ykLibDemo/com.ykstudio.ykLibDemo.SuperImageViewActivity paused=false}
 Start proc com.ykstudio.ykLibDemo for activity com.ykstudio.ykLibDemo/.MainActivity: pid=734 uid=10035 gids={}
 Low Memory: No more background processes.
 Got RemoteException sending setActive(false) notification to pid 626 uid 10035
 Displayed com.ykstudio.ykLibDemo/.MainActivity: +1s306ms

ヘルプ!何かご意見は?...

4

1 に答える 1

0

ドキュメントを正しく理解していれば、使用するたびに再インスタンス化する必要なく、BitmapRegionDecoder を再利用できます。再利用しようとしただけですか?

そして、私は同意しなければなりません: 誰もが BitmapRegionDecoder をこのシナリオ (OOM を実行せずに大きなビットマップを表示する) に使用する必要があると書いていますが、それを正しい方法で使用する方法を正確に知っている人は誰もいません :(

于 2012-10-23T08:16:22.430 に答える