2

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.

ここで、私が行ったいくつかのランダムな観察について:

  1. を使用して while ループに遅延を導入するとThread.sleep()LockCanvas()時間はさらに長くなり、遅延量でスケーリングされます。

  2. Invalidate()Snake の例の/ onDraw()drawing-process を使用すると、この問題がまだ発生します。

  3. アプリケーションはデスクトップ上で完全に実行されますが、同様に単純な libgdx プロジェクトでもこれと同じ不安定さが見られます。

  4. (物理) Samsung Galaxy SIII でデバッグしています。

  5. 幅 1 ピクセル、高さ 1ピクセルlockCanvas()の「ダーティ」Rectangleを指定しても、何も高速化されません。

  6. マニフェスト ファイルでは、設定android:hardwareAccelerated="true"は役に立ちません。

  7. マニフェスト ファイルで、supports-screens を設定しandroid:anyDensity="true"ても役に立ちません。

  8. .apk にビルドしてインストールしても役に立ちません。

  9. 変更されていないジェットボーイ ゲームを実行すると、途切れが見られます。

ジェットボーイの例に慣れていない人のために、次の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();
}

この問題を修正する方法がわからない場合でも、自分のセットアップでこの問題が見られない場合は、描画方法とデバッグ方法について教えてください。

4

0 に答える 0