Как запустить запускаемый поток в Android через определенные промежутки времени?



Я разработал приложение для отображения некоторого текста через определенные промежутки времени на экране эмулятора Android. Я использую Handler класса. Вот фрагмент из моего кода:



handler = new Handler();
Runnable r = new Runnable() {
public void run() {
tv.append("Hello World");
}
};
handler.postDelayed(r, 1000);


при запуске этого приложения текст отображается только один раз. Зачем?

551   10  

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");
}
new Handler().postDelayed(new Runnable() {
    public void run() {
        // do something...              
    }
}, 100);

Я считаю, что для этого типичного случая, т. е. запустить что-то с фиксированным интервалом, 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();
}

чтобы посмотреть на код смотрите здесь:

пример потока, отображающий местоположение GPS и текущее время, выполняемое вместе с потоком пользовательского интерфейса main-activity

теперь в Котлине вы можете запускать потоки таким образом:

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

    Ничего не найдено.