SurfaceView.LockCanvas() 需要 15 毫秒到 75 毫秒才能完成。有没有办法解决这个问题,或者减少它的零星?
背景:我是 Android 2d 图形开发的新手,所以我从 jetboy 示例开始,并将其更改为简单地在屏幕上滚动其中一个位图(使用速度矢量和System.currentTimeMillis()
基于差异来获取经过的时间)。
位图将完美滚动一两秒,但会间歇性地停顿,看起来不连贯。
经过一些调试,我认为问题是由于SurfaceView.LockCanvas()
需要 15 毫秒到 75 毫秒才能返回Canvas
- 即使没有运行重要的更新代码并且没有任何内容被绘制到画布上。
以下是我的调试代码。从 Jetboy 示例开始,我将run()
方法替换为以下代码:
public void run() {
while (true) {
time = SystemClock.elapsedRealtime();
elapsed_cycle = time - prev_time;
prev_time = time;
if (elapsed_cycle > 35.0){
Log.d(LOCKING, String.valueOf(elapsed_cycle) + MSAFTER + String.valueOf(count) + CYCLES);
count = 0;
}
else count++;
elapsed_draw += elapsed_cycle;
if (elapsed_draw > 30){
elapsed_draw -= 30;
c = null;
try {c = mSurfaceHolder.lockCanvas(null);} catch (IllegalArgumentException e) {Log.d("ERROR", "Lock Canvas 1.");}
if (c != null) {mSurfaceHolder.unlockCanvasAndPost(c);} else {Log.d(ERROR, "Couldn't unlock.");System.exit(0);}
}
}
}
因此,代码做了两件事:1)每 30 毫秒尝试锁定而不是解锁画布。2) 如果 while 循环的任何单个循环(迭代)花费的时间超过 35 毫秒,则会生成 LogCat 输出。运行此代码会给出以下 LogCat 输出:
07-03 13:07:44.587: D/LOCKING(4805): 39ms, after 24 cycles.
07-03 13:07:44.757: D/LOCKING(4805): 39ms, after 5 cycles.
07-03 13:07:44.838: D/LOCKING(4805): 50ms, after 1 cycles.
07-03 13:07:45.048: D/LOCKING(4805): 44ms, after 5 cycles.
07-03 13:07:45.799: D/LOCKING(4805): 74ms, after 41 cycles.
07-03 13:07:49.432: D/LOCKING(4805): 36ms, after 215 cycles.
这里是未过滤的 LogCat 的味道:
07-03 13:33:11.058: D/BatteryService(712): update start
07-03 13:33:11.068: D/BatteryService(712): level:99 scale:100 status:2 health:2 present:true voltage: 4332 temperature: 315 technology: Li-ion AC powered:false USB powered:true icon:17303207 invalid charger:0
07-03 13:33:11.078: D/LOCKING(5804): 39ms, after 40 cycles.
07-03 13:33:11.088: D/STATUSBAR-BatteryController(896): onReceive() - ACTION_BATTERY_CHANGED
07-03 13:33:11.088: D/STATUSBAR-BatteryController(896): onReceive() - level:99
07-03 13:33:11.088: D/STATUSBAR-BatteryController(896): onReceive() - plugged:2
07-03 13:33:11.088: D/STATUSBAR-BatteryController(896): onReceive() - BATTERY_STATUS_CHARGING:
07-03 13:33:11.088: D/STATUSBAR-PhoneStatusBar(896): ACTION_BATTERY_CHANGED
07-03 13:33:11.118: W/AlarmManager(712): FACTORY_ON= 0
07-03 13:33:11.128: E/MtpService(1013): In MTPAPP onReceive:android.intent.action.BATTERY_CHANGED
07-03 13:33:11.128: E/MtpService(1013): battPlugged Type : 2
07-03 13:33:11.128: D/LOCKING(5804): 49ms, after 0 cycles.
现在对于我所做的一些随机观察:
如果我在 while 循环中引入延迟,
Thread.sleep()
那么LockCanvas()
时间会更长,随着延迟量的增加。Invalidate()
我仍然使用 Snake 示例的/onDraw()
drawing-process看到这个问题。我在一个类似简单的 libgdx 项目中看到了同样的波动,尽管该应用程序可以在桌面上完美运行。
我正在(物理)三星 Galaxy SIII 上进行调试。
提供1 像素宽度和 1 像素高度
lockCanvas()
的“脏”Rectangle
并不会加快任何速度——我认为做更少的工作可能会更快乐。在清单文件中,设置
android:hardwareAccelerated="true"
没有帮助。同样在清单文件中,设置 supports-screens
android:anyDensity="true"
没有帮助。构建到 .apk 并安装没有帮助。
运行未更改的喷气机游戏时,我看到了波涛汹涌的感觉。
对于不熟悉 jetboy 示例的人,onCreate()
方法如下:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// get handles to the JetView from XML and the JET thread.
mJetBoyView = (JetBoyView)findViewById(R.id.JetBoyView);
mJetBoyThread = mJetBoyView.getThread();
// look up the happy shiny button
mButton = (Button)findViewById(R.id.Button01);
mButton.setOnClickListener(this);
mButtonRetry = (Button)findViewById(R.id.Button02);
mButtonRetry.setOnClickListener(this);
// set up handles for instruction text and game timer text
mTextView = (TextView)findViewById(R.id.text);
mTimerView = (TextView)findViewById(R.id.timer);
mJetBoyView.setTimerView(mTimerView);
mJetBoyView.SetButtonView(mButtonRetry);
mJetBoyView.SetTextView(mTextView);
}
线程从这里开始:
public void surfaceCreated(SurfaceHolder arg0) {
// start the thread here so that we don't busy-wait in run()
// waiting for the surface to be created
thread.setRunning(true);
thread.start();
}
即使您不知道如何解决此问题,如果您在自己的设置中没有看到此问题,那么我很乐意听取您的意见,了解您的绘图方式和调试方式。