2012年5月3日木曜日

強制停止になる原因

ようやく、ソースが触れる環境に帰ってきました。
で、早速エラーレポートで報告されている事案の調査をしました。

ちなみに、落ちたクラス(VgeSurfaceView)のソースは↓のような感じ。
/*
*------------------------------------------------------------------------
* メインループ (スレッド)
*------------------------------------------------------------------------
*/
@Override
public void run() {
SurfaceHolder holder=getHolder();
Canvas canvas;
while (isAttached) {
// 仮想VRAMへの描画処理
PSGTEST.setVram(vram);
// 仮想VRAMを実VRAMへ転送
canvas=holder.lockCanvas();
canvas.drawBitmap(vram,vramRect,screenRect,screenPaint);
holder.unlockCanvasAndPost(canvas);
}
}

赤い網掛け部分がNullPointerExceptionが発生した部分。
なので、青い網掛け(lockCanvas)がnullを返したことが原因。

Android SDKのマニュアルを読んでいたら、妙な記述を発見。(以下、抜粋)
If you call this repeatedly when the Surface is not ready (before Callback.surfaceCreated or after Callback.surfaceDestroyed), your calls will be throttled to a slow rate in order to avoid consuming CPU.

上記を逆説すれば、「リトライは必要」ということ。
(ついでに、リトライ時にsleepをしなくてもハングにはならないらしい)

なので、以下のように修正すればOKかな。
Invader BlockとVGE Chiptune Musicの両方に下記の対策を入れて、本日中にリリース予定です。
public void run() {
SurfaceHolder holder=getHolder();
Canvas canvas;
while (isAttached) {
// 仮想VRAMへの描画処理
IBLOCK.setVram(vram);
// 仮想VRAMを実VRAMへ転送
canvas=holder.lockCanvas();
while(null==canvas && isAttached) canvas=holder.lockCanvas();
if(null==canvas) break;
canvas.drawBitmap(vram,vramRect,screenRect,screenPaint);
holder.unlockCanvasAndPost(canvas);
}
}
修正ポイント:
・リトライ要の場合、リトライ(Destroy時は中断して抜ける)
・リトライ中にDestroyになった場合はスレッド停止

久々にAndroidアプリ開発っぽい内容の記事でした。

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。

合理的ではないものを作りたい

ここ最近、実機版の東方VGSの開発が忙しくて、東方VGSの曲追加が滞っています。 東方VGS(実機版)のデザインを作りながら検討中。基本レトロUIベースですがシークバーはモダンに倣おうかな…とか pic.twitter.com/YOYprlDsYD — SUZUKI PLAN (...