私のアプリは、独自のスレッドで実行されている SurfaceView と、メイン アプリケーション スレッドで実行されている一連の通常のビューを組み合わせています。ほとんどの場合、これで問題なく動作します。ただし、SurfaceView のスレッドで何かを実行して、メイン アプリケーション スレッドの UI 要素の 1 つを変更しようとすると、android.View.ViewRoot$CalledFromWrongThreadException が発生します。
これを回避する正しい方法はありますか?asynctask を使用する必要がありますか? Runonuithread()? それとも、独自のスレッドで SurfaceView をメイン スレッドの他の UI 要素と混在させることは、本質的に悪いことなのでしょうか?
私の質問が意味をなさない場合は、より明確な疑似コードを次に示します。
// Activity runs on main application thread
public class MainActivity extends Activity {
RelativeLayout layout;
TextView popup;
MySurfaceView mysurfaceview;
protected void onCreate(Bundle savedInstanceState) {
...
setContentView(layout);
layout.addView(mysurfaceview); // Surface View is displayed
popup.setText("You won"); // created but not displayed yet
}
public void showPopup() {
layout.addView(popup);
}
}
// Surface View runs on its own separate thread
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener {
private ViewThread mThread;
public boolean onTouch(View v, MotionEvent event) {
...
if (someCondition == true) {
mainactivity.showPopup();
// This works because onTouch() is called by main app thread
}
}
public void Draw(Canvas canvas) {
...
if (someCondition == true) {
mainactivity.showPopup();
// This crashes with ViewRoot$CalledFromWrongThreadException
// because Draw is called by mThread
// Is this fixable?
}
}
}