Java 针对月球着陆器示例,surfaceView中运行线程的非法线程例外
因此,我有一个应用程序,它使用一个表面视图,为UI运行一个单独的线程。它几乎是直接从月球着陆示例应用程序中获取的。该应用程序还在另一个线程上使用蓝牙服务,但我确信这与问题无关,因为我可以一起禁用蓝牙,但这种情况仍然存在 我的应用程序中的问题是,当关闭然后重新打开时,除了抛出错误外,该应用程序不会在thread.start之后开始运行UI线程。在Lunar示例中,onSurfaceCreated方法中有thread.start。问题是,当我重新启动应用程序时,它会在Pause上调用,然后在SurfaceDestroy上,线程已经在运行,当我尝试启动它时,会出现错误。我的onSurfaceCreated、onPause、onResume和onsurfacedestromed代码与示例完全相同。我知道如果this.getState==Thread.State.NEW{,我可以使用它,但这似乎会掩盖我的一些其他问题。我想掌握活动生命周期 我的问题是月球着陆器是如何停止线程的?为什么我的不停止使用相同的代码并在onSurfaceCreated方法上运行。显然我遗漏了一些东西。据我所知,在月球示例中,destroy的线程上唯一调用的是thread.join 编辑3:如果需要的话,这里是答案 这是我的surfaceview中的三种覆盖方法Java 针对月球着陆器示例,surfaceView中运行线程的非法线程例外,java,android,multithreading,Java,Android,Multithreading,因此,我有一个应用程序,它使用一个表面视图,为UI运行一个单独的线程。它几乎是直接从月球着陆示例应用程序中获取的。该应用程序还在另一个线程上使用蓝牙服务,但我确信这与问题无关,因为我可以一起禁用蓝牙,但这种情况仍然存在 我的应用程序中的问题是,当关闭然后重新打开时,除了抛出错误外,该应用程序不会在thread.start之后开始运行UI线程。在Lunar示例中,onSurfaceCreated方法中有thread.start。问题是,当我重新启动应用程序时,它会在Pause上调用,然后在Surf
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
Log.d(TAG, "surfaceCreated");
// start the bluetooth service
thread.startBluetoothService();
// start the game
//if (this.getState() == Thread.State.NEW) {
Log.d(TAG, "thread start");
// start running the thread
this.start();
//}
Log.d(TAG, "running to true");
// release the thread lock
setRunning(true);
}
// surfaceChanged is called at least once after surfaceCreated
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.d(TAG, "surfaceChanged");
// reset the surface size
thread.setSurfaceSize(width, height);
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Log.d(TAG, "surfaceDestroyed");
// make sure to shut down the thread cleanly
boolean retry = true;
// stop the running thread
thread.setRunning(false);
// continuously try to shut down the thread
while (retry){
try{
// blocks calling thread until termination
thread.join();
// stop the bluetooth service
//thread.stopBluetoothService();
retry = false;
}catch(InterruptedException e){
//try to shut it down again
}
}
}
我真的很迷茫。任何帮助都将不胜感激,谢谢
编辑:
所以我做了更多的测试。当用户点击Home并在Pause上完全退出应用程序时,然后像我之前所说的那样点击onSurfaceDestroy。然后当它重新启动时,我得到onResume,然后是onSurfaceCreated。我想我的问题是,当你重新进入应用程序时,它没有调用onCreate
还有一些问题。。。
onPause和onDestroy之间的区别是什么?我想我的问题是,因为onCreate没有被调用,所以我没有一个新创建的UI线程,看起来它仍然在运行
即使在onPause上也应该停止线程吗?因为这样我就不需要运行onCreate来重新实例化线程了。下面是onCreate代码
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wobble);
// get view and thread
wobbleView = (WobbleView) findViewById(R.id.wobble);
wobbleThread = wobbleView.getThread();
// Get local Bluetooth adapter
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// If the adapter is null, then Bluetooth is not supported
if (mBluetoothAdapter == null) {
// alert the user of bluetooth failure
Toast.makeText(this, "Bluetooth is not available, using internal devices sensors", Toast.LENGTH_LONG).show();
// set the data source to internal sensors - so we'll just use the devices accel
wobbleThread.setDataSource(WobbleThread.INTERNAL_SENSORS);
// bluetooth is supported so make sure its enabled and
}else{
// make sure bluetooth is enabled on the device
if (!mBluetoothAdapter.isEnabled()) {
Log.d(TAG, "starting request to enable bluetooth");
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
// all is well with bluetooth - use bluetooth
Log.d(TAG, "setting bluetooth to bluetooth");
wobbleThread.setDataSource(WobbleThread.BLUETOOTH);
}
// give the LunarView a handle to the TextView used for messages
wobbleView.setTextView(
(TextView) findViewById(R.id.text_accel),
(TextView) findViewById(R.id.game_msg),
(TextView) findViewById(R.id.text_score),
(TextView) findViewById(R.id.bluetooth_status)
);
if (savedInstanceState == null) {
// we were just launched: set up a new game
//wobbleThread.setState(wobbleThread.STATE_READY);
} else {
//wobbleThread.setRunning(true);
// we are being restored: resume a previous game
//wobbleThread.restoreState(savedInstanceState);
}
}
编辑2:
一些logcat输出
这就是我在重新打开应用程序后调用thread.start时得到的结果
11-18 22:50:44.104 4868-4868/com.bme.shawn.wobble E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.IllegalThreadStateException: Thread already started
at java.lang.Thread.checkNotStarted(Thread.java:871)
at java.lang.Thread.start(Thread.java:1025)
at com.bme.shawn.wobble.WobbleThread.startGame(WobbleThread.java:213)
at com.bme.shawn.wobble.WobbleView.surfaceCreated(WobbleView.java:94)
at android.view.SurfaceView.updateWindow(SurfaceView.java:580)
at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:240)
at android.view.View.dispatchWindowVisibilityChanged(View.java:7903)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1071)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1071)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1071)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1071)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1289)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1050)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5750)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:791)
at android.view.Choreographer.doCallbacks(Choreographer.java:591)
at android.view.Choreographer.doFrame(Choreographer.java:561)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:777)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:150)
at android.app.ActivityThread.main(ActivityThread.java:5406)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
如果我使用thread.getState检查并绕过错误,我会在关闭时收到这个错误,然后重新打开应用程序。在这种情况下,当应用程序重新打开时,基本上会登录所有内容。线程根本没有绘制。这非常奇怪,因为如果没有检查,我会收到一个错误,表示线程已经在运行
11-18 22:59:13.444 5345-5345/com.bme.shawn.wobble D/WobbleActivity﹕ onPause
11-18 22:59:13.584 5345-5345/com.bme.shawn.wobble D/WobbleView﹕ surfaceDestroyed
11-18 22:59:17.794 5345-5345/com.bme.shawn.wobble D/WobbleActivity﹕ onResume
11-18 22:59:17.804 5345-5345/com.bme.shawn.wobble D/WobbleView﹕ surfaceCreated
11-18 22:59:17.804 5345-5345/com.bme.shawn.wobble D/WobbleThread﹕ running to true
11-18 22:59:17.804 5345-5345/com.bme.shawn.wobble D/WobbleView﹕ surfaceChanged
11-18 22:59:17.804 5345-5345/com.bme.shawn.wobble D/WobbleThread﹕ setting surface sizes
11-18 22:59:17.824 5345-5345/com.bme.shawn.wobble D/dalvikvm﹕ GC_FOR_ALLOC freed 3343K, 2% free 6585K/6668K, paused 13ms, total 13ms
11-18 22:59:17.844 5345-5345/com.bme.shawn.wobble E/IMGSRV﹕ :0: PVRDRMOpen: TP3, ret = 44
11-18 22:59:17.854 5345-5345/com.bme.shawn.wobble E/IMGSRV﹕ :0: PVRDRMOpen: TP3, ret = 50
在surfaceCreated中创建一个新的线程实例并启动它。然后调用thread.join in surfaceDestroyedto销毁它。发布您的logcat输出。好了,谢谢提醒我。月球着陆器示例不这样做怎么办?他们正在同步surfaceView,并在pause restore and unpause meth中显式设置状态od。我也在这样做。我使用一个SetStateMode方法,该方法也会像同步SurfaceHolder一样同步SurfaceHolder。我使用此方法将其设置为在onPause方法中暂停。我在视图点击上以相同的方式取消暂停。您是否尝试过创建新实例?是否有效?尚未尝试。我是否应该在视图中创建thread的实例结构者?