我制作了一个带有两个窗口的应用程序,当我从主窗口转到首选项时,一切都很好,但是当我尝试返回主活动应用程序崩溃时,Thread已经启动错误。
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new GameView(this));
startService(new Intent(this, MyService.class));
}
public void onResume(){
super.onResume();
}
// Initiating Menu XML file (menu.xml)
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.layout.menu, menu);
return true;
}
public void onBackPressed() {
super.onBackPressed();
stopService(new Intent(this, MyService.class));
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
更新: 这是来自LogCat的日志(我正在使用Eclipse):
09-30 11:59:17.348: D/AndroidRuntime(2917): Shutting down VM
09-30 11:59:17.348: W/dalvikvm(2917): threadid=1: thread exiting with uncaught exception (group=0x40aa7210)
09-30 11:59:17.368: E/AndroidRuntime(2917): FATAL EXCEPTION: main
09-30 11:59:17.368: E/AndroidRuntime(2917): java.lang.IllegalThreadStateException: Thread already started.
09-30 11:59:17.368: E/AndroidRuntime(2917): at java.lang.Thread.start(Thread.java:1045)
09-30 11:59:17.368: E/AndroidRuntime(2917): at com.examples.todolist.GameView$1.surfaceCreated(GameView.java:45)
ManiFest文件(来自它的活动):
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<service
android:name="MusicService"
android:enabled="true">
</service>
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="PreferencesActivity"></activity>
<service android:enabled="true" android:name=".MyService" />
</application>
在我的项目中,我有MainActivity.java - 它是主窗口,PreferencesActivity.java - 它是首选项窗口,GameView.java - 负责绘制东西,GameManager.java - 控制FPS。在游戏视图中,我有main,onDraw和onTouch事件。 以下是GameView的主要内容:
public GameView(Context context) {
super(context);
gameLoopThread = new GameManager(this);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameLoopThread.setRunning(false);
while (retry) {
try {
gameLoopThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
bmp1 = BitmapFactory.decodeResource(getResources(),
R.drawable.wall_sprite);
}
这是一个gameManager.java,因为我发现它与run有关。我仍然试图找出如何使线程(或屏幕?)被破坏然后重新制作它。
公共类GameManager扩展了线程{
static final long FPS = 30;
private GameView view;
private boolean running = false;
// class constructor
public GameManager(GameView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
public void run() {
long ticksPS = 1000 / FPS;
long startTime;
long sleepTime;
while (running) {
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS - (System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e) {
}
}
}
}
答案 0 :(得分:0)
好的就是交易,surfaceCreated()似乎持有一个线程,并且该线程只能启动一次且只能启动一次。这是当前的问题。
public void surfaceCreated(SurfaceHolder holder) {
gameLoopThread.setRunning(true);
// This is unsafe
gameLoopThread.start();
}
在不了解应用程序的整个设计的情况下,有几种方法可以多次触发。
可以创建,销毁Surface,然后可以创建新曲面。在这种情况下,GameView将具有相同的线程引用并尝试再次启动它。所以你有SurfaceView的Activity-A。创建Surface,然后启动另一个活动,表面视图可能会在onPause()的周围被销毁。您完成首选项并返回到您的活动,onResume()被调用,您的表面将被重新创建......两次点火。这是假设你的应用程序是这样的: 活动 - &gt; PreferencesActivity - &gt;原始活动。
你似乎开始了另一项任务,所以我不确定你为什么这样做,但旧的活动仍然在后台,所以如果它恢复,它可能会重建表面。
不确定GameManager是什么,但它看起来像某种运行循环。如果已经存在,您可以确保它未启动。或者,如果存在可能需要单独的GameManager实例的情况,您可以跟踪多个实例并确保不再启动它们。