12

我正在编写 2d 教程,并且能够在三星 Galaxy Tab 上测试我当前的教程部分。

本教程只是在屏幕上随机移动默认图标。轻按一下,我创建了一个新的移动图标。只要屏幕上有 25 个或更少的元素,Galaxy 上的一切都可以正常工作(恒定为 60fps)。

使用第 26 个元素,帧速率降至 25fps。

当我将图像的大小/尺寸更改为更大时,我在第 26 个元素之前达到不到 25fps。没关系。但是在某些不可重现的元素数量下,帧从(大部分超过)10fps 下降到 1fps。

在我的 Nexus One 上,我可以添加 150 个元素并且仍然有 50fps。

我所做的:我将位图变量更改为静态变量,因此并非每个元素都有自己的图像,但都使用相同的图像。这消除了这种行为,但我怀疑这个解决方案是一个好的解决方案。神奇的数字 25 表明我只能以这种方式使用 25 个不同的图像。

有人知道什么会导致这种行为吗?是三星修改安卓版的bug吗?

我的示例 Eclipse 项目可用。如果一些三星所有者能用样品检查他们的性能,我将不胜感激。

编辑

一位同事找到了解决方案。他改变了位图的加载方式

mBitmap = BitmapFactory.decodeResource(res, R.drawable.icon);

mBitmap = BitmapFactory.decodeStream(new BufferedInputStream(res.openRawResource(R.drawable.icon)));

但我们仍然不明白为什么它会这样工作......

4

3 回答 3

5

好吧,我一直在看你的项目,一切似乎都很好,但我知道是什么导致你的帧速率下降。

您在运行时分配对象。如果您不这样做,它将使您在开始时创建所有对象,因此您应该直接注意到显着下降(如果我的解决方案不能解决您的问题)。

那就是说;我不确定对象池是否能解决您的问题,但您可以尝试。在构造函数中初始化您的对象,而不是在其中进行此调用onTouchEvent():

new Element(getResources(), (int) event.getX(), (int) event.getY())

你应该有类似的东西mElement.add(objectPool.allocate()),对象池在池中找到一个未使用的对象。此外,我们应该在该对象池中有指定数量的对象,然后您可以从那里检查是导致此错误的分配还是其他原因。

使用第 26 个元素,帧速率降至 25fps。

当(或者如果)你实现了这个,你应该直接看到帧率下降(如果这不能解决你的问题),因为对象池会让你在开始时分配一个固定的数量(例如,可能 100 个元素?)(但你没有在视觉上使用它们)。

此外,我在我的 Android 示例应用程序之一中使用了内存池模式(对象池)。在那个样本中;Canvas我在onTouchEvent()使用对象池(在运行时不分配)上添加了一行。在该源代码中,您可以轻松更改对象的总数并检查并自己尝试。如果您想查看我的示例应用程序(和源代码),请写下评论,我很乐意分享它,因为它尚未公开。我的评论是用瑞典语写的,但我认为你应该能够理解,因为变量和方法都是用英文写的。:)

旁注:您写道,您已经尝试(甚至成功)通过将Bitmap static. 就像现在一样,您的元素具有不同的 a 实例Bitmap,这将使您在Bitmap每次构建新对象时都分配一个新对象。这意味着每个对象Bitmap在使用相同资源时都指向不同的对象。static是一个完全有效的解决方案(虽然 25 的幻数似乎很奇怪)。

这种Bitmap情况可以类比OpenGL系统。如果您有 20 个对象都应该使用相同的资源,则有两种可能的解决方案:它们可以指向相同的 VRAM 纹理,或者它们可以指向不同的 VRAM 纹理(例如您不使用时的情况static),但是仍然是相同的资源。

编辑

这是我的 Android 示例应用程序,它演示了内存池。

关于您的解决方案BitmapFactory,这可能取决于该类的工作方式。我不确定,但我认为其中一种decode...()方法会生成一个新的Bitmap,即使它是相同的资源。可能是从内存new BufferedInputStream(res.openRawResource(R.drawable.icon))中重用的情况BufferedInputStream,尽管这是一个很大的猜测。

您应该做的(在这种情况下)是解码资源并将来自它的引用存储在 Panel 类中,然后将该引用传递给new Element(bitmapReference, ...)。这样,您只需分配一次,并且每个元素都指向Bitmap内存中的相同元素。

于 2011-04-20T14:12:00.567 回答
3

我已经在 HTC Desire HD 上尝试了您的代码,并且在使用 Android 2.2 目标添加第 20 张图像后,帧速率下降到无法使用。当我导出与 android 2.1 版相同的代码时,它运行良好,可以处理 200 多个实例!我怀疑这与在 2.2 上创建 GraphicObject 类的实例有关,但不太确定......

于 2011-03-18T11:38:49.207 回答
1

我相信我可以对这个问题有所了解。

至少在我的 Galaxy S、Gingerbread 2.3.5 上,第一个代码使用 Bitmap.Config = ARGB_8888 将我的 test.png 加载到位图中,而第二个代码使用 Bitmap.Config = RGB565 加载。奇怪的是,虽然 Gingerbread 默认应该创建 32 位表面,但 RGB565 的“渲染”(我分析并比较了对 drawBitmap 的原生调用)要快得多。

因此,第二个想法,更适合您的整个示例,是 ARGB888 位图确实具有 alpha,因此在这种情况下,渲染 25 个以上精灵的重叠图像可能会在 alpha 计算算法中产生一些瓶颈,而 RGB565 图像会很好和快。

于 2012-05-20T17:52:03.623 回答