为什么我的应用程序在更新方法中使用setText时会强制关闭?

时间:2010-11-13 22:00:55

标签: java android textview

我有一个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();
    }

我虽然发布了整个应用程序,因为它相对较小,所以我可以得到一些帮助而不会产生混淆。

3 个答案:

答案 0 :(得分:3)

首先,当您获得Force Close对话框时,在Eclipse中使用adb logcat,DDMS或DDMS透视图来检查LogCat并查看与崩溃相关的堆栈跟踪。

在这种情况下,您的异常将是“无法从非UI线程修改用户界面”的效果。您试图从后台线程调用setText(),这不受支持。

如果您正在使用2D / 3D图形,则使用GameThread是有意义的。它不适合基于小部件的应用程序。有manymanymanymany示例演示了如何在不使用GameThread的情况下创建基于窗口小部件的应用程序。

答案 1 :(得分:1)

你必须从UI线程调用它。

有关详细信息,请查看:Painless Threading

如果您决定使用处理程序,最简单的解决方案是:

  1. 扩展一个视图,覆盖它的onDraw,在它绘制游戏对象之后,当然首先为它们计算游戏数据

  2. 处理程序:(在您的活动中)

    private Handler playHandler = new Handler() {

    public void handleMessage(Message msg) {

        gameView.postInvalidate(); // gameView is the View that you extended
    

    }

    };

  3. 游戏主题有一个简单的

  4.   

    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