我想优化视差滚动视图与多个大位图.在我的Nexus 5,一切都很顺利,Traceview转储看起来像这样:
x1c 0d1x的数据
doFrame()方法使用~18 ms完成。
然而,当使用Nexus 7或Android 6模拟器(Genymotion)时,Traceview转储看起来像这样:
的
nSyncAndDrawFrame方法现在在运行完全相同的应用程序时需要大约300毫秒。
有趣的代码部分在parallax视图的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条答案
按热度按时间bvjxkvbb1#
在
CollapsingToolbarLayout
中遇到一个大图像(1920x933)的类似行为后,我偶然发现了这个问题。分析器显示,对android.view.ThreadedRenderer.nSyncAndDrawFrame()
的调用需要很长时间才能完成。虽然降低图像分辨率(例如,降低到1280x622)可以消除这个问题,但有一种方法可以完全避免这个问题。
将图像移到
drawable-nodpi
文件夹中,这表明图像与分辨率无关。渲染延迟应该消失。bxgwgixi2#
在我的情况下,问题是大图像。例如,对于背景,我有一个大小为800x800的图像,当我将这个大小缩小到400x400时,问题就消失了。
ao218c7q3#
在某些设备上(例如:HTC One)我在绘制不断变化的位图时也遇到了同样的情况。这是由将位图复制到GPU内存造成的。自从上次绘制以来,我的应用程序更改位图,并在位图不断复制到GPU内存之后。如果GPU内存不足,则复制需要很长时间。要解决这个问题,有几个选项:
*缩小位图大小:GPU内存足够持续复制。
*禁用硬件加速(设置
LAYER_TYPE_SOFTWARE
):这样系统就不需要不断地将位图复制到GPU内存中。我在应用程序中添加了禁用硬件加速的选项。为了获得更好的理解,你可以查看这篇文章:
检查GPU渲染
参考文件:
hardware-accel
profile-gpu