Что эквивалентно setInterval / setTimeout JavaScript в Android / Java?

129

Может ли кто-нибудь сказать мне, существует ли эквивалент для setInterval / setTimeout для Android? Есть ли у кого-нибудь пример того, как это сделать?

karse23
источник

Ответы:

245

Как всегда с Android, есть много способов сделать это, но если вы просто хотите запустить фрагмент кода немного позже в том же потоке, я использую это:

new android.os.Handler().postDelayed(
    new Runnable() {
        public void run() {
            Log.i("tag", "This'll run 300 milliseconds later");
        }
    }, 
300);

.. это в значительной степени эквивалентно

setTimeout( 
    function() {
        console.log("This will run 300 milliseconds later");
    },
300);
Бен Клейтон
источник
Это очень хорошее решение для выбора ящика и фрагментации
транзакций
6
Как я могу отменить его, если мне нужно?
Квентин Рой,
Как получить объем действия в методе run ()?
Энди
@Andy вот так:MyActivityName.this.myFunctionOnActivity()
Бен Клейтон
1
@QuentinRoy: Handler timeout = new Handler(); final Runnable r = new Runnable{...}; timeout.postDelayed(r, 300);и если вы хотите отменить это:timeout.removeCallbacks(r);
Bastian Springer
101

setInterval ()

функция, которая повторяется каждые n миллисекунд

Javascript

 setInterval(function(){ Console.log("A Kiss every 5 seconds"); }, 5000);

Приблизительный эквивалент Java

new Timer().scheduleAtFixedRate(new TimerTask(){
    @Override
    public void run(){
       Log.i("tag", "A Kiss every 5 seconds");
    }
},0,5000);

SetTimeout ()

функция, которая работает только через n миллисекунд

Javascript

setTimeout(function(){ Console.log("A Kiss after 5 seconds"); },5000);

Приблизительный эквивалент Java

new android.os.Handler().postDelayed(
    new Runnable() {
        public void run() {
            Log.i("tag","A Kiss after 5 seconds");
        }
}, 5000);
Midhun
источник
5
Что касается scheduleAtFixedRateметода, как вы отмените таймер внутри действия после его завершения?
Авроранил
2
@ user824294 вы можете сохранить свой экземпляр Timer в переменной и вызвать «cancel ()», когда вы хотите остановить запланированные задачи - Timer t = new Timer (); t.scheduleAtFixedRate (...); - А затем вызовите t.cancel (); когда хотите.
Aebsubis 01
14

Если вас не беспокоит разбудить телефон или вернуть приложение из мертвых, попробуйте:

// Param is optional, to run task on UI thread.     
Handler handler = new Handler(Looper.getMainLooper());
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        // Do the task...
        handler.postDelayed(this, milliseconds) // Optional, to repeat the task.
    }
};
handler.postDelayed(runnable, milliseconds);

// Stop a repeating task like this.
handler.removeCallbacks(runnable);
SharkAlley
источник
На моем телефоне (Huawei P Smart) обработчик не выводит устройство из спящего режима ( как заметил apanloco в другом ответе )
Франко
13

В зависимости от того, чего вы действительно хотите достичь, вам следует взглянуть на обработчики Android:

http://developer.android.com/reference/android/os/Handler.html

Если вы ранее использовали javascript setTimeout () и т. Д. Для планирования задачи, которая будет запускаться в будущем, это способ сделать это в Android (postDelayed / sendMessageDelayed).

Обратите внимание, что ни обработчики, ни таймеры не выводят телефон Android из спящего режима. Другими словами, если вы хотите запланировать что-то, что действительно произойдет, даже если экран выключен / процессор спит, вам также необходимо проверить AlarmManager.

apanloco
источник
5

Я не очень разбираюсь в JavaScript, но думаю, что таймеры могут быть тем, что вы ищете.

http://developer.android.com/reference/java/util/Timer.html

По ссылке:

One-shot запланированы на абсолютное время или после относительной задержки. Повторяющиеся задачи планируются либо с фиксированным периодом, либо с фиксированной ставкой.

nicholas.hauschild
источник
Примечание: он вызывает вас в фоновом потоке, а не в основном потоке / пользовательском интерфейсе.
Pang
Это не ответ, а ссылка на внешнюю информацию, которая может содержать или не содержать решение OP. Пожалуйста, вставьте соответствующий код, который OP может использовать!
Лев
5

Первый ответ, безусловно, правильный, и именно на нем я основал эту лямбда-версию, которая намного короче по синтаксису. Поскольку Runnable имеет только 1 метод переопределения run (), мы можем использовать лямбда:

this.m_someBoolFlag = false;
new android.os.Handler().postDelayed(() -> this.m_someBoolFlag = true, 300);
neoRiley
источник
5
import java.util.Timer;
import java.util.TimerTask;

class Clock {
    private Timer mTimer = new Timer();

    private int mSecondsPassed = 0;
    private TimerTask mTask = new TimerTask() {
        @Override
        public void run() {
            mSecondsPassed++;
            System.out.println("Seconds passed: " + mSecondsPassed);
        }
    };

    private void start() {
        mTimer.scheduleAtFixedRate(mTask, 1000, 1000);
    }

    public static void main(String[] args) {
        Clock c = new Clock();
        c.start();
    }
}
Jeeva
источник
4

Вот эквивалент setTimeout, наиболее полезный при попытке обновить пользовательский интерфейс после задержки.

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

new AsyncTask<Void, Void, Void>() {
        @Override
        protected Void doInBackground(Void... params) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
            }

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            // Update the User Interface
        }

    }.execute();
Стефан ДЖЕЙС
источник
3
1. Точно onProgressUpdate()также можно использовать для моделирования setInterval(). 2. AsyncTask работает в пуле потоков (или только в одном потоке), поэтому a. возможно, придется подождать, пока AsyncTaskзакончит другой ; б . он займет один поток из пула.
Pang
В этом контексте существует много проблем с использованием задачи async (только один поток и блокировка потока без причины) - другие решения намного лучше.
Elemental
4

Я создавал mp3-плеер для Android, я хотел обновлять текущее время каждые 500 мс, поэтому я сделал это так

setInterval

private void update() {
    new android.os.Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            long cur = player.getCurrentPosition();
            long dur = player.getDuration();
            currentTime = millisecondsToTime(cur);
            currentTimeView.setText(currentTime);
            if (cur < dur) {
                updatePlayer();
            }

            // update seekbar
            seekBar.setProgress( (int) Math.round((float)cur / (float)dur * 100f));
        }
    }, 500);
}

который рекурсивно вызывает тот же метод

ZeroErr0r
источник
0

Котлин:

Вы также можете использовать CountDownTimer:

class Timer {
    companion object {
        @JvmStatic
        fun call(ms: Long, f: () -> Unit) {
            object : CountDownTimer(ms,ms){
                override fun onFinish() { f() }
                override fun onTick(millisUntilFinished: Long) {}
            }.start()
        }
    }
}

И в вашем коде:

Timer.call(5000) { /*Whatever you want to execute after 5000 ms*/ }
Фотон
источник