Почему приложение закрывается, когда я устанавливаю текст в методе обновления? - PullRequest
0 голосов
/ 14 ноября 2010

У меня есть приложение для Android, над которым я просто экспериментирую, и я не могу понять, почему приложение закрывается, когда я обновляю TextView через цикл while. Когда я комментирую метод 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 ]

3 голосов
/ 14 ноября 2010

Во-первых, когда вы получаете диалоговое окно Force Close, используйте adb logcat, DDMS или перспективу DDMS в Eclipse, чтобы проверить LogCat и посмотреть трассировку стека, связанную с вашей аварией.

В этом случаевашим исключением будет что-то вроде «Невозможно изменить пользовательский интерфейс из потока, не являющегося пользовательским интерфейсом».Вы пытаетесь вызвать setText() из фонового потока, что не поддерживается.

Использование GameThread имеет смысл, если вы используете 2D / 3D графику.Это не подходящий шаблон для приложений на основе виджетов.Есть много , много , много , много примеров, демонстрирующих, как создавать приложения на основе виджетов без использования GameThread.

1 голос
/ 14 ноября 2010

Вы должны вызывать его из потока пользовательского интерфейса.

Для получения дополнительной информации проверьте: Потоки безболезненно .

Если вы решите использовать обработчик, самое простое решениедля вас будет:

  1. Расширить представление, переопределить его onDraw, в нем нарисовать игровые объекты, после того как вы сначала рассчитали игровые данные для них, конечно,

  2. Обработчик: (в вашей деятельности)

    private Handler playHandler = new Handler() {

    public void handleMessage(Message msg) {

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

    }

    };

  3. В игровом потоке есть простой

Message.obtain (playHandler) .sendToTarget ();

В двух словах, представление отвечает за чертеж (вы можете переместить вычисления в отдельный класс и вызвать его до onDraw), поток отвечает только за запланированные вызовы обработчика.и обработчик несет ответственность только за то, чтобы сказать представлению перерисовать себя.

0 голосов
/ 14 ноября 2010

Вы не можете обновить пользовательский интерфейс своего приложения вне потока пользовательского интерфейса, который является «основным» потоком, в котором вы запускаете. В onCreate (Context) вашего приложения вы создаете объект игрового потока, что и делаетобновление вашего пользовательского интерфейса.

Вы должны использовать обработчик:
http://developer.android.com/reference/android/os/Handler.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...