IllegalThreadStateException in LunarLander --Android
7412 ワード
IllegalThreadStateException in LunarLander
実験LunarLanderの場合run LunarLanderの途中でHomeを押してreturnを押すのではなく飛び出した場合、このときLunarLanderに入るとIllegalThreadStateExceptionという例外を飛び出してしまうということを少し検討してみましたまずこの図を見て、緑の枠でReturn、この2つのボタンを押してメインメニューに戻ると、戻るゲームの異なるReturnライフサイクルの変化 surfaceCreated:LunarThread を生成する surfaceDestroyed:LunarThread を消滅
修正方法は以下の通りです.太字は私が追加したプログラムコードsurfaceCreated
実験LunarLanderの場合run LunarLanderの途中でHomeを押してreturnを押すのではなく飛び出した場合、このときLunarLanderに入るとIllegalThreadStateExceptionという例外を飛び出してしまうということを少し検討してみましたまずこの図を見て、緑の枠でReturn、この2つのボタンを押してメインメニューに戻ると、戻るゲームの異なるReturnライフサイクルの変化
onCreate->onStart->onResume-> Retuen ->onPause->onStop->onDestroy
-> LunarLander ->onCreate ->onStart->onResume
Homeライフサイクルの変化
onCreate->onStart->onResume-> Home ->onPause->onStop
-> LunarLander ->onRestart ->onStart->onResume
の上に戻ると、Returnを押すと、Activity全体が通常のプログラムに従ってDestroyがCreateに戻りますが、Homeを押してメインメニューに戻るとActivityはDestroyが落ちません.彼の資料は依然として記憶体に存在し、その後はRestart彼にすぎないが、LunarLanderゲームの設計はSurfaceViewのライフサイクルがActivityと一致していると仮定し、ActivityのCreateとDestroyの間に一度だけ発生するsurfaceCreateとsurfaceDestroyがホームを押すのを観察するとき、SurfaceViewのライフサイクル
onCreate->onStart->onResume
onWindowFocusChanged ->surfaceCreated ->surfaceChanged -> Home ->onPause->surfaceDestroyed ->onWindowFocusChanged ->onStop
-> LunarLander ->onRestart ->onStart->onResume->surfaceCreated
-> surfaceChanged -> onWindowFocusChanged
は上記のように、Activityは通常のプログラムに従ってDestroyに落とされずにActivityのcreateとdestroyの間でSurfaceViewのcreateとDestroyが1回以上実行されているため、ゲームデザイナーとしての予想外なので、IllegalThreadStateExceptionという例以外では実行できないBugが発生し、IllegalThreadStateExceptionはどのように発生しているのでしょうか.まず、彼の定義
Thrown when an operation is attempted which is not possible given the state that the executing thread is in.
、つまり同じプログラムからstart同じThreadを例
Thread t=new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
}});
t.start();
t.start();//start , IllegalThreadStateException
として避けようとするが、この例外を避けるには、新しいThread
Thread t=new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
}});
t.start();
t=new Thread(..........);
t.start();
を使用しなければならない.Lunar、I llegalThreadStateExceptionはLunarViewのsurfaceCreatedから投げ出された
/*
* Callback invoked when the Surface has been created and is ready to be
* used.
*/
public void surfaceCreated(SurfaceHolder holder) {
....
thread.start();// IllegalThreadStateException
}
である.surfaceCreatedはActivityで2回以上実行すると同じthreadが2回以上startされるので、threadの発生はActivityのonCreate呼び出し構築式LunarViewの時に誕生するので、
public LunarView(Context context, AttributeSet attrs) {
....
thread = new LunarThread(holder, _context, new Handler() {
@Override
public void handleMessage(Message m) {
mStatusText.setVisibility(m.getData().getInt("viz"));
mStatusText.setText(m.getData().getString("text"));
}
});
....
}
が1回しか発生しません.ここで私は暴力法の解決策を提案してこのBugを解決します.surfaceCreatedの時に新しいLunarThreadが発生します.これで同じthreadが2回以上startされるのを避けることができますが、私はStateのRetoreをしていないので、彼はReturnを押すのと同じように新しいゲームを始めました.私のやり方はLunarThreadのライフサイクルをSurfaceと一致させることです.修正方法は以下の通りです.太字は私が追加したプログラムコードsurfaceCreated
public void surfaceCreated(SurfaceHolder holder) {
/* thread null, Thread*/
if (thread == null) {
/*
thread copy , ,
*/
thread = new LunarThread(holder, _context, new Handler() {
@Override
public void handleMessage(Message m) {
mStatusText.setVisibility(m.getData().getInt("viz"));
mStatusText.setText(m.getData().getString("text"));
}
});
setFocusable(true);
/* , Home , thread
ready keyEvent
*/
thread.setState(LunarThread.STATE_READY);
}
thread.setRunning(true);
thread.start();
}
surfaceDestroyed
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
thread.setRunning(false);
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
}
}
/* thread null thread
surfaceCreated if(thread==null)
*/
thread=null;
}
onWindowFocusChanged
public void onWindowFocusChanged(boolean hasWindowFocus) {
if (!hasWindowFocus)
{
/*surfaceDestroy onWindowFocusChanged
thread null
surfaceCreated Ready
*/
if(thread!=null)
thread.pause();
}
}
以上です.変更が完了すると、大きな成果が得られます.------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------本当にゲーム全体から飛び出して、ActivityのonDestroyで彼を呼ぶしかありません(surfaceDestroyで実行緒を終わらせるよりも)しかし私は本当に上の案を実作していません.ただ構想ですが、八九は十から離れません.