Как сделать 10-секундную задержку?
Здравствуйте. Необходимо реализовать задержку подобно, как на аукционах, то есть человек загрузил фото, у второго оно загрузилось на смарте, и он нажимает кнопку — проходит 10 секунд, и если из всех, кто нажал под этой фоткой, он первый — ему об этом сообщается. Хочется понимания от более опытных будущих коллег, новичок_
Отслеживать
11 1 1 золотой знак 2 2 серебряных знака 8 8 бронзовых знаков
задан 19 янв 2015 в 4:02
33 1 1 золотой знак 1 1 серебряный знак 3 3 бронзовых знака
А причем тут Android? Это надо на сервере делать.
19 янв 2015 в 5:36
3 ответа 3
Сортировка: Сброс на вариант по умолчанию
Хочу дополнить тему еще одним способов сделать задержку.
Принятый вариант будет вызывать блокировку текущего потока, в нашем случае UI, чтобы этого избежать, используйте этот вариант, он позволяет выполнять требуемое в другом потоке.
Java
Handler handler = new Handler(); handler.postDelayed(new Runnable() < public void run() < /*code*/ >>, 2000); //specify the number of milliseconds
Kotlin
val handler = android.os.Handler() handler.postDelayed(< /*code*/ >, 2000) //specify the number of milliseconds //Или android.os.Handler().postDelayed(< /*code*/ >, 2000)
Coroutine
CoroutineScope(Dispatchers.IO).launch
Можно использовать функцию расширение
object Coroutines < fun io(work: suspend (() ->Unit)): Job = CoroutineScope(Dispatchers.IO).launch < work() >fun ioThenMain(work: suspend (() -> T?), callback: ((T?) -> Unit)): Job = CoroutineScope(Dispatchers.Main).launch < val data = CoroutineScope(Dispatchers.IO).async rt@< return@rt work() >.await() callback(data) > >
Coroutines.ioThenMain(< //выполнение идет в отдельном потоке >) < //Результат приходит в ui поток >
Как сделать не мгновенный переход\перезагрузку Activity?
Я хочу что бы после правильного ответа кнопка светилось зеленым, и переходил к следующему вопросу.
Но у меня это происходит мгновенно и нечего таково не видно, как сделать задержку перехода так чтоб цвет кнопки успел сменится, типа переход через 500мс.
Остановка потока не работает ведь все зависает на Nмс, тестировал эти два способа.
Thread.sleep(500);
и
// Handler из android.os.Handler; Handler handler = new Handler(); handler.postDelayed(new Runnable() < public void run() < /* Code */ >>, 500);
Эти два способа не работают у меня, просто зависает.
- Вопрос задан более двух лет назад
- 93 просмотра
2 комментария
Простой 2 комментария
Создание задержки в Java
Часто в процессе написания программ на Java возникает необходимость создать задержку или паузу в выполнении кода. Например, во время цикла while или for нужно, чтобы выполнение кода приостановилось на определенное количество секунд.
Допустим, есть цикл, который перебирает элементы массива или списка, и перед каждым следующим шагом необходимо сделать паузу:
for (int i = 0; i < arr.length; i++) < // Некоторые операции с элементами массива // Нужно сделать задержку перед следующим шагом >
В таких случаях в Java можно использовать метод Thread.sleep() , который приостанавливает выполнение текущего потока на заданное количество миллисекунд.
for (int i = 0; i < arr.length; i++) < // Некоторые операции с элементами массива try < Thread.sleep(1000); // Задержка в 1 секунду >catch (InterruptedException e) < e.printStackTrace(); >>
Здесь Thread.sleep(1000); приостанавливает выполнение текущего потока на 1000 миллисекунд, то есть на 1 секунду. Обратите внимание, что это может вызвать исключение InterruptedException , поэтому этот код обязательно должен быть обернут в блок try-catch.
Это простой и эффективный способ создать задержку в Java. Однако стоит помнить, что Thread.sleep() приостанавливает выполнение всего потока, а не только цикла, в котором он вызывается. Поэтому его использование может быть нецелесообразно, если в том же потоке выполняются другие важные задачи.
Класс Handler
Класс android.os.Handler является дальнейшим развитием потоков, упрощающий код. Handler может использоваться для планирования выполнения кода в некоторый момент в будущем. Также класс может использоваться для передачи кода, который должен выполняться в другом программном потоке.

Рассмотрим максимально простой пример для знакомства
private Handler mHandler; boolean gameOn; long startTime; @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startTime = System.currentTimeMillis(); mHandler = new Handler()< public void handleMessage(Message msg)< super.handleMessage(msg); if(gameOn) < long seconds = ((System.currentTimeMillis() - startTime)) / 1000; Log.i("info", "seconds text-warning">Периодическое выполнение задачи При сложных вычислениях может понадобиться очередь Runnable-объектов. Помещая объект в очередь, вы можете задать время его запуска. Для демонстрации использования обработчика потока напишем программу, запускающую фоновый процесс, который будет каждые 200 миллисекунд получать текущее время и обновлять текст. Нам понадобится кнопка Пуск и две текстовые метки, в которых будет отображаться время и количество нажатий кнопки:
package ru.alexanderklimov.handler; import android.os.Bundle; import android.os.Handler; import android.os.SystemClock; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.TextView; public class MainActivity extends AppCompatActivity < // считаем нажатия кнопки private int mButtonPressed = 0; // счетчик времени private long mTime = 0L; private TextView mCounterTextView; private TextView mTimeTextView; // обработчик потока - обновляет сведения о времени // Создаётся в основном UI-потоке private Handler mHandler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTimeTextView = (TextView) findViewById(R.id.textViewTime); mCounterTextView = (TextView) findViewById(R.id.textViewCounter); if (mTime == 0L) < mTime = SystemClock.uptimeMillis(); mHandler.removeCallbacks(timeUpdaterRunnable); // Добавляем Runnable-объект timeUpdaterRunnable в очередь // сообщений, объект должен быть запущен после задержки в 100 мс mHandler.postDelayed(timeUpdaterRunnable, 100); >> // Описание Runnable-объекта private Runnable timeUpdaterRunnable = new Runnable() < public void run() < // вычисляем время final long start = mTime; long millis = SystemClock.uptimeMillis() - start; int second = (int) (millis / 1000); int min = second / 60; second = second % 60; // выводим время mTimeTextView.setText("" + min + ":" + String.format("%02d", second)); // повторяем через каждые 200 миллисекунд mHandler.postDelayed(this, 200); >>; @Override protected void onPause() < // Удаляем Runnable-объект для прекращения задачи mHandler.removeCallbacks(timeUpdaterRunnable); super.onPause(); >@Override protected void onResume() < super.onResume(); // Добавляем Runnable-объект mHandler.postDelayed(timeUpdaterRunnable, 100); >public void onClick(View v) < mCounterTextView.setText("" + ++mButtonPressed); >>
На экране будет отображаться время и одновременно мы можем нажимать на кнопку. Эти действия не мешают друг другу, так как работают в разных потоках.

Кроме метода postDelayed() вы можете использовать метод postAtTime():
postAtTime(Runnable r, long uptimeMillis)
В этом случае объект r добавляется в очередь сообщений, запуск объекта производится во время, заданное вторым параметром.
Самый простой способ помещения объекта в очередь - метод post(), когда указывается только помещаемый объект без указания времени выполнения объекта:
post(Runnable r)
Пример с индикатором прогресса
Всё, что вам нужно - создать экземпляр класса Handler в классе активности. Поток будет работать с объектом Handler, который в свою очередь, будет обновлять шкалу индикатора в основном потоке активности.
Чтобы послать сообщение в объект Handler, сначала необходимо вызвать метод obtainMessage(), чтобы извлечь объект Message из глобального пула сообщений.
Для вставки сообщения в очередь сообщений объекта Handler существует несколько методов:
- sendMessage() — помещает сообщение в очередь немедленно (в конец очереди)
- sendMessageAtFrontofQueue() — помещает сообщение в очередь немедленно и, кроме того, помещает это сообщение впереди очереди (по умолчанию оно ставится в конец очереди), таким образом ваше сообщение берет приоритет над всеми другими
- sendMessageAtTime() — помещает сообщение в очередь в установленное время в миллисекундах
- sendMessageDeiayed() — помещает сообщение в очередь после задержки, выраженной в миллисекундах
Чтобы обрабатывать эти сообщения, для объекта Handler необходимо реализовать метод обратного вызова handleMessage(), который будет вызываться каждым сообщением из очереди сообщения.
Для примера создадим приложение с ProgressBar, который будет отображать ход выполнения длительной задачи (это будет простой цикл с приостановкой потока на 1 секунду в каждой итерации цикла) и обновлять степень завершения этой задачи через объект Handler в классе активности.
package ru.alexanderklimov.progressbar; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.ProgressBar; public class ProgressBarDemoActivity extends Activity < ProgressBar mProgressBar; int mProgress = 0; @Override public void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mProgressBar = (ProgressBar) findViewById(R.id.progressBarHorizontal); new Thread(myThread).start(); >private Runnable myThread = new Runnable() < @Override public void run() < while (mProgress < 100) < try < myHandler.sendMessage(myHandler.obtainMessage()); Thread.sleep(1000); >catch (Throwable t) < >> > Handler myHandler = new Handler() < @Override public void handleMessage(Message msg) < mProgress++; mProgressBar.setProgress(mProgress); >>; >; >

Splash-screen
Очень часто программисты используют Handler для реализации окна приветствия, которое автоматически закрывается и следом запускается основная активность игры или приложения.
public classSplashActivity extends Activity < @Override protected voidonCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); newHandler().postDelayed(new Runnable() < @Override public void run() < startActivity(newIntent( SplashActivity.this, MainMenuActivity.class)); finish(); >>, 2000); > >