2012-07-17 133 views
4

我想写一个小部件来显示图像从SDCARD,具有平移/缩放功能。 在意识到大多数图像不会像完全采样的位图那样适合内存之后,我尝试了一些更复杂的操作 - 我将获得整个图像的下采样位图以进行快速平移和缩放,以及高分辨率裁剪出的部分图像的视口上将显示的内容将在背景中计算出来,并在完成后分配给低分辨率(单独的线程)。Android - 内存泄漏时使用BitmapRegionDecoder

经过分配搜索后,我终于找到了可以为我加载图像的一部分,没有内存异常在过程中的伟大和holly BitmapRegionDecoder。

WOO-HOO,对吧?

Only ...虽然在许多图像之间切换 - 我发现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的仿真器上运行。

这里是logcat的,仅筛选MEM TAG:

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 

帮助!任何想法?...

回答

0

如果我正确理解文档,您可以重新使用BitmapRegionDecoder,而无需在每次使用它时重新实例化它。你是否试图重用它?

而且我必须同意:大家写道,BitmapRegionDecoder应该用于此方案(显示大位图,而不会在OOM),但没有人确切地知道如何使用它的正确方法:(