0

проблема что я пытаюсь заменить тест объекта через цикл, он меняется всё хорошо, но мне нужно чтобы это было с задержкой. я вписал Thread.sleep(1000); но за этого он в самом начале показывает белый экран. после чего выводит последний элемент массива

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
Str str = new Str();
Thread thr = new Thread(str);

thr.start();

} public class Str implements Runnable { public void run() { TextView text = findViewById(R.id.message); String[] array = new String[]{"Hi", "it`s", "my", "feast", "mobile", "application"}; for (int i = 0; i < array.length; i++) { try { Thread.sleep(1000); } catch (InterruptedException ex) { ex.printStackTrace(); } text.setText(array[i]); } } };

введите сюда описание изображения

  • вы блокируете главный поток, который отвечает за UI.
    вам надо создать новый отдельный поток и в нем выполнять и задержку и изменение в UI.
    – Wlad Dec 31 '22 at 19:40
  • Если выводить в консоль, всё работает – David Tepols Dec 31 '22 at 19:48
  • Создал второй поток, так же всё – David Tepols Dec 31 '22 at 20:29
  • Если вы создаете новые потоки, то покажите это в вопросе. Сейчас в вопросе этого нет. Отредактировать вопрос можно, нажав на кнопку править под вопросом. – Vadik Sirekanyan Dec 31 '22 at 21:44
  • Отредактировал вопрос. – David Tepols Jan 01 '23 at 20:28
  • Но появилась новая ошибка, да теперь экран не белый или чёрный, но приложение крашит – David Tepols Jan 01 '23 at 20:47
  • Из потока нельзя менять UI. Нужно перебрасывать эту задачу обратно в UI-поток. Например так: `final String text = array[i];

    runOnUiThread(() -> text.setText(text));`

    – woesss Jan 01 '23 at 20:57
  • final String text = array[i]; где это заменить нужно? – David Tepols Jan 01 '23 at 21:09
  • text.setText(array[i]); - вот это в цикле заменить на код из комментария выше – woesss Jan 01 '23 at 21:27
  • Я не специалист в этой теме, но может быть использовать java.util.Timer? – Зонтик Jan 02 '23 at 11:31
  • Вот здесь сказано, почему так происходит: https://ru.stackoverflow.com/questions/338436/%D0%98%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BC%D0%B5%D1%82%D0%BE%D0%B4%D0%B0-sleep Это swing, но суть та же – Зонтик Jan 02 '23 at 11:38

2 Answers2

1

Попробуйте так:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    TextView text = findViewById(R.id.message);
    // Обработчик сообщений.
    // Обравбатывает сообщения в главном (UI) потоке.
    Handler handler = new Handler(Looper.getMainLooper());
    // Отправляем сообщение
    handler.post(new Runnable() {
        final String[] array = new String[]{"Hi", "it`s", "my", "feast", "mobile", "application"};
        int index = 0;
        @Override
        public void run() {
            if (index < array.length) {
                text.setText(array[index++]);
                // Отправляем сообщение с задержкой.
                handler.postDelayed(this, 1000);
            }
        }
    });
}
-1

Мне кажется,что проще использовать класс java.util.Timer. Он сам создаёт новый поток и предназначен как раз для того, чтобы выполнять действие через какое-то время несколько раз, и именно это вы и пытаетесь сделать.

Ваша проблема в том, что когда вы останавливаете поток, то вы на самом деле "замораживаете" весь UI. Что происходит "за кулисами", очень хорошо и подробно описано здесь, и пересказывать это я не вижу смысла.

Как использовать таймер? Вообще, обычно создают целый класс для таймера, что-то вроде этого:

import java.util.TimerTask;
import java.util.Timer;

public class SomeClass extends TimerTask{ @Override public void run(){ //Какие-то действия }

public void test(){ Timer timer = new Timer(); timer.schedule(this,0,1000);//Назначаем таймер } }

Но в вашем случае лучше использовать анонимный класс:

import java.util.TimerTask;
import java.util.Timer;

...

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);

String[] array = new String[]{&quot;Hi&quot;, 
&quot;it`s&quot;, &quot;my&quot;, &quot;feast&quot;, &quot;mobile&quot;, &quot;application&quot;}; //Ваш массив
int counter; //Переменная-счётчик, почти как в цикле

Timer timer = new Timer(); //Создаём объект класса Timer
timer.schedule(new TimerTask(){ //Назначаем таймер, используя анонимный класс
   @Override
   public void run(){ 
      text.setText(array[counter]);
      counter++; //Увеличиваем счётчик на 1
      if(counter == array.size){
         timer.cancel(); //Отменяем таймер, когда массив закончится
      }
   }
},0,1000); //Таймер будет выполнять действие раз в 1000 милисекунд


}

Надеюсь, мой ответ полезен. Вот ещё ссылка на документацию: https://docs.oracle.com/javase/6/docs/api/java/util/Timer.html

Зонтик
  • 2,262
  • 2
  • 11
  • 39
  • Те же грабли, что и у автора с потоком - попытка изменения UI не из UI-потока приведёт к крэшу. – woesss Jan 03 '23 at 09:25
  • @ woesss не могу с вами согласиться! Я лично использую таймер для графического интерфейса, и это работает! Ведь таймер не замораживает поток, а вызывает метод run() раз в какое-то время. – Зонтик Jan 03 '23 at 13:10
  • А собственный поток создаёт лишь для того, чтобы вызывать метод run(). И никакого tread.sleep()! – Зонтик Jan 03 '23 at 13:40
  • Прежде чем спорить сами запустите этот код. Note: The entire view tree is single threaded. You must always be on the UI thread when calling any method on any view. If you are doing work on other threads and want to update the state of a view from that thread, you should use a Handler. https://developer.android.com/reference/android/view/View#event-handling-and-threading – woesss Jan 03 '23 at 16:30
  • @ woesss Timer и UI вполне "дружат": https://developer.alexanderklimov.ru/android/java/timer.php – Зонтик Jan 04 '23 at 15:34
  • Вы внимательно статью-то читали? Перечитайте второй абзац и примеры кода рассмотрите в этом контексте. – woesss Jan 04 '23 at 16:00
  • @ woesss И чем таймер нарушает ваше условие? Посмотрите вот это, тут почему-то всё работает: developer.alexanderklimov.ru/android/java/timer.php – Зонтик Jan 06 '23 at 04:13