Android-view.Surface OutOfResourcesException

Android-view.Surface OutOfResourcesException,android,memory,memory-leaks,view,allocation,Android,Memory,Memory Leaks,View,Allocation,当我使用ListView导航和标准菜单键在Android应用程序内部移动时,我的Android应用程序似乎没有发布视图。在加载了大约100个不同的(10个左右的独特视图)后,它开始滞后和黑屏 错误日志: 07-01 09:54:42.913: INFO/ActivityManager(1279): Starting: Intent { cmp=com.site.android.conferencecompanion/.Search } from pid 31290 07-01 09:54:43.

当我使用ListView导航和标准菜单键在Android应用程序内部移动时,我的Android应用程序似乎没有发布视图。在加载了大约100个不同的(10个左右的独特视图)后,它开始滞后和黑屏

错误日志:

07-01 09:54:42.913: INFO/ActivityManager(1279): Starting: Intent { cmp=com.site.android.conferencecompanion/.Search } from pid 31290
07-01 09:54:43.013: ERROR/msm7x30.gralloc(1279): /dev/pmem: no more pmem available
07-01 09:54:43.013: ERROR/msm7x30.gralloc(1279): couldn't open pmem (No such file or directory)
07-01 09:54:43.013: ERROR/msm7x30.gralloc(1279): gralloc failed err=Out of memory
07-01 09:54:43.013: WARN/GraphicBufferAllocator(1279): alloc(480, 800, 1, 00000133, ...) failed -12 (Out of memory)
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279): Allocated buffers:
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x290740: 1500.00 KiB |  480 ( 480) x  800 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x307448:   60.00 KiB |  102 ( 128) x  120 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x32e4c0:   71.25 KiB |  480 ( 480) x   38 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x3caad8:   60.00 KiB |  102 ( 128) x  120 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x4a47f8: 1346.25 KiB |  480 ( 480) x  718 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x4f9710: 1500.00 KiB |  480 ( 480) x  800 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x54c500: 1500.00 KiB |  480 ( 480) x  800 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x5d1c00: 1500.00 KiB |  480 ( 480) x  800 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x5f5f98: 1500.00 KiB |  480 ( 480) x  800 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x604600:   60.00 KiB |  126 ( 128) x  120 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x60a3d0:  750.00 KiB |  480 ( 480) x  800 |        4 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x661270: 1428.75 KiB |  480 ( 480) x  762 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x6830b8:  750.00 KiB |  480 ( 480) x  800 |        4 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x70e0e8: 1500.00 KiB |  480 ( 480) x  800 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x71f238:   71.25 KiB |  480 ( 480) 
07-01 09:54:43.013: ERROR/SurfaceFlinger(1279): Layer::requestBuffer(this=0x189d50), index=0, w=480, h=800 failed (Out of memory)
07-01 09:54:43.013: ERROR/Surface(31290): Surface (identity=4545) requestBuffer(0, 0, 0, 0, 00000033) returned a buffer with a null handle
07-01 09:54:43.013: ERROR/Surface(31290): getBufferLocked(0, 0, 0, 0, 00000033) failed (Out of memory)
07-01 09:54:43.013: ERROR/Surface(31290): dequeueBuffer failed (Out of memory)
07-01 09:54:43.013: ERROR/ViewRoot(31290): OutOfResourcesException locking surface
07-01 09:54:43.013: ERROR/ViewRoot(31290): android.view.Surface$OutOfResourcesException
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.view.Surface.lockCanvasNative(Native Method)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.view.Surface.lockCanvas(Surface.java:314)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.view.ViewRoot.draw(ViewRoot.java:1457)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.view.ViewRoot.performTraversals(ViewRoot.java:1259)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1860)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.os.Looper.loop(Looper.java:123)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.app.ActivityThread.main(ActivityThread.java:3839)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at java.lang.reflect.Method.invokeNative(Native Method)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at java.lang.reflect.Method.invoke(Method.java:507)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at dalvik.system.NativeStart.main(Native Method)
07-01 09:54:43.203: INFO/ActivityManager(1279): Displayed com.site.android.conferencecompanion/.Search: +292ms
adb外壳转储系统窗口
显示以下内容:

#1 - #29, junk
#30: AppWindowToken{40bbc000 token=HistoryRecord{408cc260 com.site.android.conferencecompanion/.ProgramDates}}

...

#142: AppWindowToken{40ba65a8 token=HistoryRecord{40b93808 com.site.android.conferencecompanion/.ProgramSpeakers}}
所以,如果我理解正确的话,大约有112个视图被保存在内存中。我能做些什么吗?是否有我丢失的支票、标志或参数?我是不是误解了垃圾场


谢谢

检查泄漏来源的一个很好的方法是,如果您在Eclipse中,请打开窗口->打开透视->DDMS,然后从进程选择中选择正在运行的进程并使用分配跟踪器。启动应用程序,但在启动分配跟踪器之前不要触摸应用程序。然后做你认为会导致问题的事情,然后每次都检查分配情况。这将准确地显示导致泄漏的代码


另外,如果您发布代码,我们可以查看一下。

尝试扩展您的活动,以便查看它们是否被垃圾收集(finalize()被调用)。类似地,尝试扩展视图以帮助识别它们是否正在被垃圾收集

如果要将视图和活动放入集合中进行缓存,请尝试使用使用WeakReference的集合对象,如WeakHashMap。您是否在视图或活动中使用内部类?如果是这样,这些类持有对活动或视图的引用,并防止它们被垃圾收集。一个很好的例子是作为内部类的AsyncTask。此任务在其自己的线程中运行,即使您已关闭活动,也可以继续保留视图


另外,看看静态变量,它们是否会附着在对象上?

这是Surface Flinger的问题,它将维护应用程序的表面并将其组合到显示设备中

试试这个:减少xml文件中的布局像素格式。

(尽管这是一年前的事,但我是通过谷歌来到这里的)

有人告诉我,一次加载的视图太多,Android无法跟踪所有视图。*这听起来像是没有正确使用ListView,这是我们很多人都感到内疚的。假设您有一个自定义阵列适配器:

public abstract View getView (int position, View convertView, ViewGroup parent)
重载此函数时,请始终选中convertView

public abstract View getView (int position, View convertView, ViewGroup parent)
{
   View view = convertView;
   if ( view == null )
   {
      // create/inflate the view here
      // ex: view = inflater.inflate(R.layout.bob, null);
      // configure the static parts here
   }
   // configure the dynamic parts here

   return view;
}
Android为listview视图提供了一个“回收站”机制,如果可能的话,它将重用视图。换句话说,它不是创建一堆不同的视图,而是从回收站获取一个旧视图

在你的例子中,你有10种不同的观点。如果它们非常相似,可以创建superview并打开或关闭部分视图(例如subView.setVisibility(view.GONE))。请注意大量的if语句块。我以前没用过,但你应该调查一下

public abstract int getItemViewType (int position)
public abstract int getViewTypeCount ()
这会更好,因为你不必处理额外的绒毛,它应该由Android自动管理

  • 就我个人而言,我不是100%确定这可能是真的,但我觉得有66%的可能性是真的

如果我可以在这里留个便条:

我在测试我的Prestigo PMP5080B时有相同的日志。 我的应用程序也会随机阻塞

我注意到,当我断开USB电缆时(通过单击“设置”即可断开与平板电脑的连接),应用程序工作正常。 我还注意到,当我使用Eclipse和USB连接到我的应用程序时,SD卡无法安装,但不知道这个问题是否以某种方式连接到我的应用程序,因为我没有存储在SD上


我也遇到了同样的问题,最终解决了。 解决方案:

从Eclipse启动您的应用程序,并在Eclipse中不断观察LogCat控制台的同时玩一点。开始新活动或类似活动时,您应该看到:

Tag:"WindowManagerImpl", Text:"addView, new view, mViews[1]:....".
这里重要的是
mViews[x]-part
。x告诉您有多少视图处于活动状态。 现在,当您启动一个活动,但mViews计数器告诉您它有5-10个新视图时,您可以确定您无意中创建了太多视图。 这样您就可以找到代码中的弱点

这发生在我的游戏应用程序中:每次我输掉游戏,都会启动5个或更多新的GameOverActivity,因为启动新GameOverActivity的代码处于循环中。因此,在玩了几分钟后,有20个未使用的游戏概述耗尽了我的资源。
(所以在循环中启动活动时要小心。)

在我的例子中,出现错误是因为我使用Window类更改状态栏的颜色,而这种颜色仅在高于21的android构建版本中受支持。将以下内容添加到代码中可能会起作用

if(Build.VERSION.SDK_INT >= 21) {

//... your code with Window class here

}

你对上下文或视图(隐式地保存上下文)有任何静态引用吗?@Scott:我不这么认为,我怎么能确定?简单地使用static关键字是一个很好的开始。这里有一些关于Android漏洞的基本文档:你能澄清一下你在代码中做什么吗?这是在一个活动中发生的吗?或者,当用户选择ListView项目时,您是否通过调用意图来启动多个活动?关于如何启动/加载新视图的代码示例可能不错。我会尝试一下,不幸的是整个应用程序似乎都在这样做,所以我没有一个可以发布的代码实例。也许我能抓到一项活动。