rlo*_*ong 12 android android-canvas
我正在制作一个带滚动背景的动态壁纸.我有两个位图对象,我之间交替,以保持下一帧的先前绘制的像素.我在画布顶部绘制一个新行,然后调用drawBitmap将其余像素复制到画布上.
我正在使用Runnable对象来完成繁重的工作.它执行所需的所有复制和计算,然后锁定画布,在持有者上输入同步块,并对Canvas.drawBitmap(位图,rect,rect,paint)进行单次调用.屏幕上偶尔会出现白色闪烁,这似乎与高CPU活动有关.在使用traceview时,我发现drawBitmap操作,特别是Canvas.native_drawBitmap(),比正常时间长得多.通常它在2-4毫秒内完成,但是当我看到白色闪光时,它可能需要10到100毫秒.
private void draw() {
SurfaceHolder holder = getSurfaceHolder();
Canvas canvas = null;
prepareFrame();
try {
canvas = holder.lockCanvas();
synchronized (holder) {
if (canvas != null) {
drawFrame(canvas);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (canvas != null)
holder.unlockCanvasAndPost(canvas);
}
afterDrawFrame();
handler.removeCallbacks(drawRunner);
if (visible) {
handler.post(drawRunner);
}
}
Run Code Online (Sandbox Code Playgroud)
该draw()函数run()在Runnable中调用.
private void prepareFrame() {
num++;
if (num%2 == 0) {
mainBmp = mainBmp1;
mainCan.setBitmap(mainBmp1);
mainCan.drawBitmap(mainBmp2, source, destination, null);
} else {
mainBmp = mainBmp2;
mainCan.setBitmap(mainBmp2);
mainCan.drawBitmap(mainBmp1, source, destination, null);
}
}
Run Code Online (Sandbox Code Playgroud)
该prepareFrame()功能是我如何保持我绘制的先前像素.被称为源的Rect是底部大小不足全屏的一行,其中目标是顶部的一行短.在drawBitmap()调用中prepareFrame()永远不会比2-4msec更长.
private void drawFrame(Canvas can) {
can.drawBitmap(mainBmp, source, destination,null);
}
Run Code Online (Sandbox Code Playgroud)
这个单一操作是在持有锁的情况下在画布上完成的.
private void afterDrawFrame() {
ca.calcNextRow();
mainBmp.setPixels(ca.getRow(), 0, canWidth, 0, 0, canWidth, 1);
}
Run Code Online (Sandbox Code Playgroud)
然后,下一个新的像素行被绘制到内存中的一个位图上.
我尝试过使用各种签名,drawBitmap()但只发现它们平均较慢,但仍会导致异常的白色闪烁.
我的整体速度很棒.没有间歇性闪光,它的效果非常好.有人有关于如何消除闪光的建议吗?
很难确切地知道这里发生了什么,因为你没有包括定义或使用一些中心变量,如"mainCan"或"ca".更完整的源参考将是伟大的.
但...
可能发生的事情是,因为drawFrame(canvas)在holder上同步,但是
handler.post(drawRunner);
Run Code Online (Sandbox Code Playgroud)
事实并非如此,当您在prepareFrame()中写入mainBmp的同时,将尝试将mainBmp绘制到系统画布.
这个问题的最佳解决方案可能是某种双缓冲,你做的事情就像
1) Write to a temporary bitmap
2) Change the ref of that bitmap to the double buffer i.e. mainBmp = tempBitmap;
Run Code Online (Sandbox Code Playgroud)
主要目标是永远不要对用于系统画布渲染的变量进行长时间写入,只需更改对象引用即可.
希望这可以帮助.
| 归档时间: |
|
| 查看次数: |
923 次 |
| 最近记录: |