互換性をチェックするために、より高いAPIレベルでテストしたいアプリをプログラムしました。API 10(2.3.3)の場合、問題はありませんでしたが、API 15(4.0.3)でアプリを実行するとすぐに、アクティビティを終了したときに、SurfaceViewの1つでNullPointerExceptionが発生しました。問題は解決したと言わざるを得ませんが、実際に例外が発生した理由がわかりません。だから多分あなたは私に言うことができます。
API10で私のために働いたコードは次のとおりです。これはrun()
-methodの一般的な構造です。
public void run() {
while (mThreadActive) {
c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
if(mState == 1) {
updateValues();
updateAnimation();
}
doDraw(c);
}
} finally {
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
アクティビティを終了するときのAPI15の場合:doDraw()
-methodが「c」に書き込もうとしたときに発生した例外。cをチェックしたところ、nullであることがわかったので、当然のことながら例外が発生しました。mThreadActive
また、falseに設定しても、while
-loopがトリガーされることを確認しました。コードサンプルは次のとおりです。
public void run() {
while (mThreadActive) {
c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
if(mState == 1) {
updateValues();
updateAnimation();
}
if(!mThreadActive) // so it really is!
Log.d("Thread", "mThreadActive is false!");
if(c == null) // so it is too!
Log.d("Thread", "c is null!");
doDraw(c); // error
}
} finally {
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
mThreadActive
-ステートメントでチェックされた後になぜfalseになるのかは想像できますが、。のwhile
後に「c」がnullになる理由はわかりませんmSurfaceHolder.lockCanvas(null)
。コードがシーケンシャルに実行されていないようです。
c != null
さて、解決策はそれを利用する前にチェックするでしょう:
public void run() {
while (mThreadActive) {
c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
if(mState == 1) {
updateValues();
updateAnimation();
}
if(c != null) // prevent drawing on c if c doesnt exist.
doDraw(c);
}
} finally {
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
では、API 10では正常に機能するのに、なぜAPI15で例外が発生するのでしょうか。もう1つの面白い点は、同じ構造を持つ他のSurfaceViewがあることですが、これと比較すると、すべて正常に機能します。コードがシーケンシャルに実行されないのはなぜですか?エミュレーター(かなり遅い)でテストしているからですか?
ありがとうございました。