我有一个Android应用程序我只是在试验一些东西,我似乎无法弄清楚为什么我的应用程序强制关闭时,我通过while循环更新TextView。当我注释掉updateText方法时,它运行正常。
public class GameThread extends Thread {
Thread t;
private int i;
private boolean running;
private long sleepTime;
GameView gv;
public GameThread() {
t = new Thread(this);
t.start();
i = 0;
sleepTime = 1000;
}
public void initView(GameView v) {
this.gv = v;
}
public void setRunning(boolean b) {
this.running = b;
}
public boolean getRunning() {
return running;
}
public void run() {
while(running) {
i++;
update();
try {
t.sleep(sleepTime);
} catch(InterruptedException e) {
}
}
}
public void update() {
gv.setText(i); // when this is uncommented, it causes force close
Log.v("Semajhan", "i = " + i);
}
public class GameView extends LinearLayout {
public TextView tv;
public GameView(Context c) {
super(c);
this.setBackgroundColor(Color.WHITE);
tv = new TextView(c);
tv.setTextColor(Color.BLACK);
tv.setTextSize(20);
this.addView(tv);
}
public void setText(int i) {
tv.setText("i count: " + i);
}
public class Exp extends Activity {
GameThread t;
GameView v;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
v = new GameView(this);
setContentView(v);
t = new GameThread();
t.setRunning(true);
t.initView(v);
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (t.getRunning() == true) {
t.setRunning(false);
Log.v("Semajhan", "STOPPED");
} else {
t.setRunning(true);
Log.v("Semajhan", "RESTART");
}
}
return true;
}
protected void onDestroy() {
Log.v("Semajhan", "DESTROYING");
super.onDestroy();
}
protected void onStop() {
Log.v("Semajhan", "Stopping");
super.onStop();
}
我虽然发布了整个应用程序,因为它相对较小,所以我可以得到一些帮助而不会产生混淆。
答案 0 :(得分:3)
首先,当您获得Force Close对话框时,在Eclipse中使用adb logcat
,DDMS或DDMS透视图来检查LogCat并查看与崩溃相关的堆栈跟踪。
在这种情况下,您的异常将是“无法从非UI线程修改用户界面”的效果。您试图从后台线程调用setText()
,这不受支持。
如果您正在使用2D / 3D图形,则使用GameThread
是有意义的。它不适合基于小部件的应用程序。有many,many,many,many示例演示了如何在不使用GameThread
的情况下创建基于窗口小部件的应用程序。
答案 1 :(得分:1)
你必须从UI线程调用它。
有关详细信息,请查看:Painless Threading。
如果您决定使用处理程序,最简单的解决方案是:
扩展一个视图,覆盖它的onDraw
,在它绘制游戏对象之后,当然首先为它们计算游戏数据
处理程序:(在您的活动中)
private Handler playHandler = new Handler() {
public void handleMessage(Message msg) {
gameView.postInvalidate(); // gameView is the View that you extended
}
};
游戏主题有一个简单的
Message.obtain(playHandler).sendToTarget();
用2个词来说,View负责绘图(你可以在单独的类中移动计算,并在onDraw之前调用它),线程只负责对Handler的调度调用,而Handler负责只是告诉View重绘自己。
答案 2 :(得分:0)
你无法在UI线程之外更新你的应用程序的UI,这是你开始的'主'线程。在你应用程序的onCreate(Context)中,你正在创建游戏线程对象,这就是做什么更新您的用户界面。
您应该使用处理程序:
http://developer.android.com/reference/android/os/Handler.html