Как обновить TextView во время зацикливания в Android? - PullRequest
7 голосов
/ 13 декабря 2010

У меня есть это:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);


    TextView debugView = (TextView)findViewById(R.id.debugView);

    for(int i=0;i<100;i++) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        debugView.setText(Integer.toString(i));
    }

}

Я ожидаю, что оно будет обновлять текстовое представление каждый раз через цикл, так что я получу: 1, 2, 3, ... 99

Вместо этого приложение ничего не делает в течение 10 секунд, а затем выдает: 99

Я предполагаю, что мне нужно обновить TextView во время цикла.Я новичок в разработке Android.Может кто-нибудь сказать мне, если это лучший способ сделать это?

Моя конечная цель состоит в том, чтобы иметь возможность обрабатывать аудиосэмплы для создания гитарного тюнера.Я пытаюсь просто визуально проверить, что приложение реагирует на внешнее аудио, и я хочу обновить TextView, чтобы продемонстрировать это.Пожалуйста, сообщите, если есть лучший способ сделать это.

Ответы [ 4 ]

22 голосов
/ 14 марта 2011

У меня была такая же проблема, и я решил ее с помощью обработчика:

public class myClass extends Activity{

 private Handler mHandler;
 private TextView text;
 private int i;

    @Override
      public void onCreate(Bundle savedInstanceState) {
          text = (TextView) findViewById(R.id.textView01);
          i = 0;
          mHandler = new Handler();
          mHandler.post(mUpdate);

      }

private Runnable mUpdate = new Runnable() {
   public void run() {

       text.setText("My number: " + i);
       i++;
       mHandler.postDelayed(this, 1000);

    }
};}

С mHandler.post(mUpdate) вы вызываете mUpdate, который является Runnable, который работает в другом потоке, который может обновлять пользовательский интерфейс. Внутри метода run() вместо создания цикла for, который будет иметь ту же проблему, что и ваш, вы устанавливаете нужный текст с помощью вспомогательной переменной, увеличиваете его и вызываете mHandler.postDelayed(this,updateTime). В этот момент представление обновляется, и у вас появляется текст на экране, и по истечении указанного вами времени (в миллисекундах) снова будет вызван RunNable mUpdate, в котором для текста будет задано следующее число на.

Надеюсь, это поможет.

8 голосов
/ 13 декабря 2010

Вам лучше использовать таймер:

    new Timer().schedule(new TimerTask() {

        @Override
        public void run() {
            runOnUiThread(new Runnable() {
                public void run() {
                    debugView.setText("something");
                }
            });
        }
    }, 0, 100);

Обратите внимание, что я использую runOnUiThread, так как вы не можете изменить представление из другого потока, который не является основным.

6 голосов
/ 13 декабря 2010

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

Посмотрите на жизненный цикл активность в Android.Это показывает, что onCreate - это только один из этапов создания Activity.Вам нужно запустить цикл в фоновом потоке и опубликовать уведомление для обновления TextView в потоке пользовательского интерфейса с помощью runOnUiThread.Ответ Кристиана показывает, как это сделать.

Однако, поскольку вашей конечной целью является обновление TextView на основе некоторого пользовательского ввода (аудио в вашем случае), вам не придется перепрыгивать через все эти циклы, чтобы сделатьэто работает.Единственная важная вещь заключается в том, что вы публикуете свои звонки для обновления пользовательского интерфейса в потоке пользовательского интерфейса, в противном случае вы получите исключения.

1 голос
/ 13 июля 2017

Вместо использования Handler можно напрямую передать Runnable для просмотра с postDelayed:

public class myClass extends Activity {

    private TextView text;
    private int i;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        text = (TextView) findViewById(R.id.textView01);
        text.postDelayed(mUpdate, 0);

    }

    private Runnable mUpdate = new Runnable() {
        public void run() {

            text.setText("My number: " + i);
            i++;
            text.postDelayed(this, 1000);

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