Как запустить запускаемый поток в Android через определенные промежутки времени?
Я разработал приложение для отображения некоторого текста через определенные промежутки времени на экране эмулятора Android. Я использую Handler класса. Вот фрагмент из моего кода:
handler = new Handler();
Runnable r = new Runnable() {
public void run() {
tv.append("Hello World");
}
};
handler.postDelayed(r, 1000);
при запуске этого приложения текст отображается только один раз. Зачем?
10 ответов:
простое исправление для вашего примера:
handler = new Handler(); final Runnable r = new Runnable() { public void run() { tv.append("Hello World"); handler.postDelayed(this, 1000); } }; handler.postDelayed(r, 1000);или мы можем использовать обычный поток, например (с оригинальным бегуном):
Thread thread = new Thread() { @Override public void run() { try { while(true) { sleep(1000); handler.post(this); } } catch (InterruptedException e) { e.printStackTrace(); } } }; thread.start();вы можете рассматривать свой запускаемый объект как команду, которая может быть отправлена в очередь сообщений для выполнения, а обработчик-как вспомогательный объект, используемый для отправки этой команды.
подробнее здесь http://developer.android.com/reference/android/os/Handler.html
Я думаю, что может улучшить первое решение Alex2k8 для обновления исправить каждую секунду
1.Исходный код:
public void run() { tv.append("Hello World"); handler.postDelayed(this, 1000); }2.Анализ
- в выше стоимости, предположим
tv.append("Hello Word")стоимостью T миллисекундах, после отображения 500 время задержки составляет 500*T МС- он будет увеличиваться с задержкой при запуске долгое время
3. Решение
чтобы избежать этого, просто измените порядок postDelayed(), чтобы избежать задержки:
public void run() { handler.postDelayed(this, 1000); tv.append("Hello World"); }
Я считаю, что для этого типичного случая, т. е. запустить что-то с фиксированным интервалом,
Timerболее уместен. Вот простой пример:myTimer = new Timer(); myTimer.schedule(new TimerTask() { @Override public void run() { // If you want to modify a view in your Activity MyActivity.this.runOnUiThread(new Runnable() public void run(){ tv.append("Hello World"); }); } }, 1000, 1000); // initial delay 1 second, interval 1 secondиспользуя
Timerесть несколько преимуществ:
- начальная задержка и интервал могут быть легко определены в
scheduleаргументов функции- таймер можно остановить, просто назвав
myTimer.cancel()- если вы хотите иметь только один поток работает, не забудьте позвонить
myTimer.cancel()до планирование нового (если myTimer не null)
для повторения задачи вы можете использовать
new Timer().scheduleAtFixedRate(task, runAfterADelayForFirstTime, repeaingTimeInterval);называй это как
new Timer().scheduleAtFixedRate(new TimerTask() { @Override public void run() { } },500,1000);приведенный выше код будет выполняться в первый раз после полсекунды(500) и повторять себя после каждого во-вторых(1000)
здесь
задание будучи метод, который будет выполняться
после время до начала выполнения
(интервал время за повторение исполнения)
во-вторых
и вы также можете использовать CountDownTimer если вы хотите выполнить задачу несколько раз.
new CountDownTimer(40000, 1000) { //40000 milli seconds is total time, 1000 milli seconds is time interval public void onTick(long millisUntilFinished) { } public void onFinish() { } }.start(); //Above codes run 40 times after each secondи вы также можете сделать это с runnable. создайте управляемый метод, например
Runnable runnable = new Runnable() { @Override public void run() { } };и назовем это обоими способами
new Handler().postDelayed(runnable, 500 );//where 500 is delayMillis // to work on mainThreadили
new Thread(runnable).start();//to work in Background
Handler handler=new Handler(); Runnable r = new Runnable(){ public void run() { tv.append("Hello World"); handler.postDelayed(r, 1000); } }; handler.post(r);
если я правильно понимаю документацию обработчика.пост() метод:
вызывает Runnable R для добавления в очередь сообщений. Runnable будет выполняться в потоке, к которому присоединен этот обработчик.
поэтому примеры, предоставленные @alex2k8, хотя и работают правильно, не совпадают. На всякий случай, где
Handler.post()используется новые потоки не создаются. Вы просто постRunnableкуда-нить сHandlerдля выполнения на времени. После этого времени выполняет толькоRunnable.run(), больше ничего.запомнить:
Runnable != Thread.
интересным примером является то, что вы можете постоянно видеть счетчик/секундомер, работающий в отдельном потоке. Также показывает GPS-местоположение. В то время как основной поток пользовательского интерфейса активности уже существует.
выдержка:
try { cnt++; scnt++; now=System.currentTimeMillis(); r=rand.nextInt(6); r++; loc=lm.getLastKnownLocation(best); if(loc!=null) { lat=loc.getLatitude(); lng=loc.getLongitude(); } Thread.sleep(100); handler.sendMessage(handler.obtainMessage()); } catch (InterruptedException e) { Toast.makeText(this, "Error="+e.toString(), Toast.LENGTH_LONG).show(); }чтобы посмотреть на код смотрите здесь:
теперь в Котлине вы можете запускать потоки таким образом:
class SimpleRunnable: Runnable { public override fun run() { println("${Thread.currentThread()} has run.") } } fun main(args: Array<String>) { val thread = SimpleThread() thread.start() // Will output: Thread[Thread-0,5,main] has run. val runnable = SimpleRunnable() val thread1 = Thread(runnable) thread1.start() // Will output: Thread[Thread-1,5,main] has run }
Котлин
private lateinit var runnable: Runnable override fun onCreate(savedInstanceState: Bundle?) { val handler = Handler() runnable = Runnable { handler.postDelayed(runnable, 2000) } handler.postDelayed(runnable, 2000) }Java
Runnable runnable; Handler handler; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { handler = new Handler(); runnable = new Runnable() { @Override public void run() { handler.postDelayed(this, 1000); } }; handler.postDelayed(runnable, 1000); }
Comments