Android-view.Surface OutOfResourcesException
当我使用ListView导航和标准菜单键在Android应用程序内部移动时,我的Android应用程序似乎没有发布视图。在加载了大约100个不同的(10个左右的独特视图)后,它开始滞后和黑屏 错误日志: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.
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%的可能性是真的
我也遇到了同样的问题,最终解决了。 解决方案: 从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项目时,您是否通过调用意图来启动多个活动?关于如何启动/加载新视图的代码示例可能不错。我会尝试一下,不幸的是整个应用程序似乎都在这样做,所以我没有一个可以发布的代码实例。也许我能抓到一项活动。