SurfaceView.LockCanvas() が完了するまでに 15 ミリ秒から 75 ミリ秒かかります。これを修正する方法、または散発性を少なくする方法はありますか?
背景: Android 2D グラフィックス開発は初めてなので、jetboy の例から始めて、ビットマップの 1 つを画面上で単純にスクロールするように変更しました (速度ベクトルとSystem.currentTimeMillis()
ベースの差を使用して経過時間を取得します)。
ビットマップは 1 ~ 2 秒間完全にスクロールしますが、断続的に一時停止し、途切れ途切れの外観になります。
SurfaceView.LockCanvas()
いくつかのデバッグの後、問題は15ms から 75ms を返すのにかかるという事実によって引き起こされると思います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);}
}
}
}
したがって、コードは次の 2 つのことを行います。1) 30 ミリ秒ごとにキャンバスのロックを解除するのではなく、単にロックしようとします。2) while ループの 1 つのサイクル (反復) が、LogCat 出力が生成されるよりも 35 ミリ秒以上かかる場合。このコードを実行すると、次の 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 プロジェクトでもこれと同じ不安定さが見られます。
(物理) Samsung Galaxy SIII でデバッグしています。
幅 1 ピクセル、高さ 1ピクセル
lockCanvas()
の「ダーティ」Rectangle
を指定しても、何も高速化されません。マニフェスト ファイルでは、設定
android:hardwareAccelerated="true"
は役に立ちません。マニフェスト ファイルで、supports-screens を設定し
android:anyDensity="true"
ても役に立ちません。.apk にビルドしてインストールしても役に立ちません。
変更されていないジェットボーイ ゲームを実行すると、途切れが見られます。
ジェットボーイの例に慣れていない人のために、次の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();
}
この問題を修正する方法がわからない場合でも、自分のセットアップでこの問題が見られない場合は、描画方法とデバッグ方法について教えてください。