1)リソースの読み込み中にスプラッシュ スクリーンを表示する場合は、バックグラウンド スレッドでできるだけ多くの読み込みを行う必要があります。GL スレッドはリソースの読み込みで忙しくないため、必要なことを何でもできるように GL スレッドを解放することをお勧めします。ただし、テクスチャのアップロードやシェーダーのコンパイルなど、OpenGL との直接的なやり取りはすべて GL スレッドで行う必要があります。
通常AsyncTask
、UI スレッドと対話する必要があるバックグラウンド リソースの読み込みに を使用します。ただし、GLSurfaceView
GL のメイン UI スレッドを使用しないため、AsyncTask
ここでは機能しません。ただし、他の方法で同様の動作をかなり簡単に取得できます。リソース コードを独自のバックグラウンド スレッドにロードし、GLSurface.queueEvent()
. バックグラウンドでのリソースの読み込みは、さまざまな方法で実行できます。この例では、バックグラウンド スレッドが 1 つの Executor を使用してみましょう。すべてが にロードされonSurfaceChanged()
、ユーザーがアプリケーションを一時停止/停止し、開始/再開した場合に再作成されることが保証されます。
private Executor mExecutor = Executors.newSingleThreadExecutor();
@Override
public void onSurfaceChanged(final int width, final int height) {
// Let's define a few states for the application; NONE, SPLASH,
// GAME.
mRenderState = NONE;
// Currently, the screen is black. Let's get something on screen as
// quickly as possible. Create a thread and start loading resources.
mExecutor.execute(new Runnable() {
@Override
public void run() {
final Resources res = mContext.getResources();
// Load splash screen resource on background thread.
final Bitmap splashBitmap = BitmapFactory.decodeResource(res, R.drawable.splash);
// Splash screen is loaded, post a Runnable that will run on the GL thread.
mGLSurfaceView.queueEvent(new Runnable() {
@Override
public void run() {
// Upload splash texture to GL, on GL thread.
GLUtils.texImage2D(GLES10.GL_TEXTURE_2D, 0, splashBitmap, 0);
// Recycle bitmap. We'll create a lot of bitmaps during loading.
// Each bitmap is only needed until we have uploaded it to GL. After
// that it's just wasting memory. Especially on older phones.
splashBitmap.recycle();
// Notify application that the splash screen is loaded,
// and it's okay to render it.
mRenderState = SPLASH;
// Screen is no longer black. User sees a splash screen,
// perhaps with a progress bar or a nice animation.
// Start loading the other textures.
// ...
// Texture loading finished.
mRenderState = GAME;
}
});
}
});
}
@Override
public void onDrawFrame()
{
if (mRenderState == SPLASH) {
// Render splash screen and a progress bar.
} else if (mRenderState == GAME) {
// Render game.
}
}
2)スプラッシュ スクリーンの読み込みにかかる時間を測定し、高速デバイスと低速デバイスで比較できます。高速デバイスと同じくらい速くロードする場合は、mRenderState を SPLASH に設定しないでください。ユーザーには黒い画面が表示され続けます。うまくいけば、黒い画面は 1 秒以内にゲームに置き換えられます。必要に応じて、リソースの読み込み中にさらにタイミングを追加し、時間がかかりすぎる場合は SPLASH レンダリング ステートを有効にすることができます。
また、スプラッシュ スクリーンのフェード インとフェード アウトは、単に画面に表示されたり表示されなくなったりするだけでなく、ユーザーを不快にさせる可能性があります。
3)吃音につながる可能性のあることがいくつかありますが、あきらめる前に少なくとも次のことを確認します。
a)メモリ管理。Android ではプロセスごとのメモリ ヒープ サイズが制限されており、古いデバイスではプロセスごとのヒープ メモリが新しいデバイスよりも大幅に少なくなります (16 ~ 32 MB と 128 MB など)。つまり、多くの重いリソースをロードしている場合、ガベージ コレクターは古いデバイスでより多くの作業を行うことになります。次のような多くのメッセージについては、「logcat」を参照してください。
D/dalvikvm: GC_CONCURRENT freed 4027K, 30% free 29173K/41635K, paused 3ms+8ms
これらは単に、以前にロードされたビットマップがメモリからフラッシュされているか、古いデバイスで GC をトリガーする他の多くのオブジェクトを作成している可能性があります。ロード中にビットマップをリサイクルすることで、これが軽減されることを願っています。
b)以下を使用して、他のプロセスが CPU を占有しているかどうかを確認します。
adb shell top -m 10
これにより、上位 10 個のプロセスの CPU 使用率が表示されます。
c)「DDMS」からメソッド プロファイリングを実行します。ゲームがカクカクしている間に、「デバイス」タブの 3 つの矢印と赤い円のある小さなボタンを押します。数秒後にもう一度押すと、プロファイリング結果が得られます。グラフの読み方を学ぶには少し時間がかかりますが、基本的には、アプリケーションのどの部分が現在 CPU を使用しているかがわかります。おそらく、最初の 10 秒間は何かが懸命に働いているのでしょう。すべてがスムーズに実行されるプロファイリング結果と比較してください。