当绘制大型位图时,nSyncAndDrawFrame极其缓慢

11

我想要优化一个带有多个大位图的视差滚动视图。在我的 Nexus 5 上,一切都很顺畅,Traceview 转储如下:

Nexus 5 上平滑滚动

doFrame() 方法使用了 ~18 毫秒才完成。

然而,当使用我的 Nexus 7 或 Android 6 模拟器(Genymotion)时,Traceview 转储看起来像这样:

Nexus 7 上渲染卡顿

现在运行完全相同的应用程序时,nSyncAndDrawFrame 方法需要 ~300 毫秒。

有趣的代码部分在视差视图的 onDraw() 中:

for (int i = 0; i < parallaxConfigManager.getNumberOfLayers(); i++) {
            Bitmap layer = parallaxConfigManager.getLayer(i);
            float dx = (offset * parallaxConfigManager.getScrollSpeedFactorForLayer(i) * imageScaleFactor);
            int offset = Math.round(-parallaxConfigManager.getBoardOffset(i) + dx);
            srcRect.offsetTo(offset, 0);

            int realWidth = getRealWidth(srcRect, layer.getWidth());
            float scaleFactor = destRect.width() / (float) srcRect.width();
            if (realWidth < srcRect.width()) {
                destRect.left       = (int) (scaleFactor * Math.max(0, -srcRect.left));
                destRect.right      = destRect.left + (int) (scaleFactor * realWidth);
            }
            destRect.bottom = Math.min(screenHeight, (int) (scaleFactor * layer.getHeight()));

            canvas.drawBitmap(layer, srcRect, destRect, paint);

            destRect.left = 0;
            destRect.right = screenWidth;
        }

然而,这段代码已经足够快了。慢的部分在于Android的本地函数nSyncAndDrawFrame()。

可能出现了什么问题?有没有办法更深入地了解这个问题?目前这个方法是一个黑盒子,因为我看不到本地调用堆栈。


3
在尝试了一番后,我认为我的应用程序在图形内存大小方面达到了极限。当我禁用一些位图时,它开始变得更快。在Nexus 5上似乎有更多的可用内存,而不是在Nexus 7上。 - Ulrich Scheller
3个回答

3
我在遇到一个大图片(1920x933)在 CollapsingToolbarLayout 中出现类似的问题后,偶然发现了这个问题。分析器显示调用 android.view.ThreadedRenderer.nSyncAndDrawFrame() 需要很长时间才能完成。
虽然将图像分辨率减小(例如到1280x622)可以消除该问题,但是有一种方法可以完全避免此问题。
将您的图像移动到 drawable-nodpi 文件夹中,这表示该图像与分辨率无关。渲染延迟应该会消失。

0
在某些设备上(例如:HTC One),当绘制不断变化的位图时,我遇到了相同的情况。 这是由于将位图复制到GPU内存所引起的。 自上次绘制以来,我的应用程序会更改位图,然后将位图不断复制到GPU内存中。 如果GPU内存不足,则复制过程会花费很长时间。 为了解决这个问题,有几个选项:
- 减小位图的大小:这样GPU内存就足够进行不断的复制。 - 禁用硬件加速(设置LAYER_TYPE_SOFTWARE):这样系统就不需要不断地将位图复制到GPU内存中。 我在我的应用程序中添加了禁用硬件加速的选项。
为了更好地理解,您可以查看这篇文章: inspect-gpu-rendering 参考资料: hardware-accel profile-gpu

0
在我的情况下,问题出在大图片上。例如,对于背景,我有一张大小为800x800的图片,当我将其缩小到400x400时,问题就解决了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接