Пауза с обработчиком и postDelayed в Android

Я очень новичок в программировании для Android, поэтому, пожалуйста, простите мой нубизм. Я пытаюсь создать очень простое действие, которое будет иметь один TextView в середине макета и просто будет переключаться на другой текст каждые пару секунд. Например, TextView скажет «текст1», сделает паузу на пару секунд, затем скажет «текст2» и снова сделает паузу. В конце концов, я хочу добавить больше текстов и заставить их все циклически повторяться один за другим. Я знаю, что это похоже на очень простая вещь, но в данный момент я в основном пытаюсь узнать о потоках и обработчиках. В любом случае, я читал о том, как мы должны держать длинные вещи вне потока пользовательского интерфейса, чтобы предотвратить ошибку, поэтому я подумал, что буду использовать обработчик чтобы просто переключаться между двумя текстами на экране. К сожалению, я не могу заставить это работать. Вот код:

public class MainActivity extends Activity {

String[] myarray = {"text1" , "text2"};
int arraylength = myarray.length;
int count;
Handler handler = new Handler();

TextView mytexts;

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

    mytexts = (TextView)findViewById(R.id.my_texts);
    mytexts.setText(myarray[0]);

    Thread t = new Thread( new Runnable(){
        public void run() {
            for (int count = 0; count < arraylength; count++){
                handler.postDelayed(new Runnable(){
                    public void run() {
                        mytexts.setText(myarray[1]);
                    }                   
                }, 7000);
            }
        }
    });
    t.start();
    }
}

Из того, что я вижу в логарифме, обработчик, кажется, запускает postDelayed один за другим (в моем случае кода он НЕ ждет 7 секунд с postDelay, чтобы сделать еще один postDelayed). Кроме того, я хотел бы сделать 1 в «mytexts.setText (myarray [1]);» быть таким же, как «count» в цикле for, поэтому он может быть таким же, как одна из строк в массиве, но это дает мне ошибку. Я застрял на этом в течение нескольких часов, и другие примеры, которые я нашел в Интернете, кажутся слишком сложными для кого-то вроде меня, который в основном хочет понять основы, прежде чем я смогу заняться другими вещами. Любая помощь вообще с любым из этого будет высоко оценена. Спасибо.


person John Octavious    schedule 15.08.2013    source источник
comment
Почему бы вам не удалить postDelayed и не использовать post с while, а затем сделать Thread.sleep(time)?   -  person Rotary Heart    schedule 15.08.2013
comment
@RotaryHeart метод postDelay отправит код, который будет выполняться в основном потоке после задержки. Вам не нужно спать нить. В данном конкретном случае ему вообще не нужна нить!   -  person Ali    schedule 15.08.2013
comment
@Ali Да, ты прав, я не хотел менять его код, а хотел сказать ему, как это сделать с этим кодом.   -  person Rotary Heart    schedule 15.08.2013
comment
На самом деле я сначала пытался использовать подход Thread.sleep, но во многих других местах я убедился, что обработчики — это способ справиться с паузами в коде. Так ли это или это просто какое-то предпочтение среди программистов?   -  person John Octavious    schedule 15.08.2013


Ответы (2)


postDelayed не блокируется, то есть он добавит его в очередь, я сделаю это позже. Итак, вы, вероятно, видите, что все обновления текста происходят вместе на 7-й секунде. Я говорю это, потому что вы postDelay используете метод onCreate, тогда как на самом деле вы, вероятно, хотите сделать это из onResume или даже onPostResume.

Также нет причин создавать поток для добавления исполняемых файлов в очередь сообщений. Ваш код должен выглядеть примерно так: (Обратите внимание на время задержки множителя)

@Override
protected void onResume() {
    super.onResume();
    for (int count = 0; count < arraylength; count++){
        handler.postDelayed(new Runnable(){
            @Override
            public void run() {
                mytexts.setText(myarray[count]);
            }
        }, 7000 * (count + 1));
    }
}
person JRomero    schedule 15.08.2013
comment
Да, все обновления текста происходят на 7-й секунде. Я немного не понимаю, почему мне не нужно создавать новую тему. Делает ли postDelayed 7-секундное ожидание в фоновом потоке автоматически? Я знаю, что это ожидание вызовет ошибку в пользовательском интерфейсе, поэтому я изначально думал, что мне нужен новый поток. - person John Octavious; 15.08.2013
comment
У вас есть это, оно будет ждать вне текущего (UI) потока. - person JRomero; 15.08.2013
comment
Добро пожаловать. Пометка вопроса как отвеченного помогает вернуть услугу ;) - person JRomero; 15.08.2013
comment
Если я поставлю 7000 вместо 7000*(count + 1) для второго параметра функции postDelayed, моя программа увидит все обновления текста, происходящие вместе на 7-й секунде. Почему? Я действительно запутался! :( - person sandra; 11.09.2014
comment
Как я уже сказал, postDelay - это временная, ну... задержка. без увеличения времени между тем, когда каждая буква все Runnable срабатывает через 7 секунд вместо 7 секунд, 14 секунд, 21 секунды и т. д. - person JRomero; 12.09.2014

Это связано с тем, что ваш цикл настраивает все ваши обработчики на запуск через 7 секунд, а не через 7 секунд друг за другом, а через 7 секунд. Вы можете либо добавить метод postDelayed, либо использовать метод postAtTime в обработчике.

Кроме того, вам не нужно делать это в потоке, вы можете вообще избавиться от этого.

person Ali    schedule 15.08.2013