Як запускати метод кожні X секунд


114

Я розробляю додаток Android 2.3.3, і мені потрібно запускати метод кожні X секунд .

В iOS у мене є NSTimer , але в Android я не знаю, що використовувати.

Хтось порекомендував мені Handler ; ще рекомендую мені AlarmManager, але я не знаю, який метод краще підходить до NSTimer .

Це код, який я хочу реалізувати в Android:

timer2 = [
    NSTimer scheduledTimerWithTimeInterval:(1.0f/20.0f)
    target:self
    selector:@selector(loopTask)
    userInfo:nil
    repeats:YES
];

timer1 = [
    NSTimer scheduledTimerWithTimeInterval:(1.0f/4.0f)
    target:self
    selector:@selector(isFree)
    userInfo:nil
    repeats:YES
];

Мені потрібно щось, що працює як NSTimer .

Що ти мені рекомендуєш?


1
Визначте "найкращий". Яким чином ви хочете, щоб це було найкраще?
Саймон Форсберг

Я не знаю, який метод краще відповідає NSTimer.
VansFannel

@VansFannel Скільки часу ви хочете?
FoamyGuy

Я оновив питання з деталями про те, що намагаюся зробити.
VansFannel

Це запитання: stackoverflow.com/questions/6242268/… , схоже на це, і має чудову відповідь.
VansFannel

Відповіді:


168

Це дійсно залежить від того, скільки часу потрібно для запуску функції.

Якщо це => 10 хвилин → я б пішов з диспетчером тривоги.

// Some time when you want to run
Date when = new Date(System.currentTimeMillis());    

try{
   Intent someIntent = new Intent(someContext,MyReceiver.class); // intent to be launched

   // note this could be getActivity if you want to launch an activity
   PendingIntent pendingIntent = PendingIntent.getBroadcast(
        context, 
        0, // id, optional
        someIntent, // intent to launch
        PendingIntent.FLAG_CANCEL_CURRENT); // PendintIntent flag

   AlarmManager alarms = (AlarmManager) context.getSystemService(
        Context.ALARM_SERVICE);

   alarms.setRepeating(AlarmManager.RTC_WAKEUP,
        when.getTime(),
        AlarmManager.INTERVAL_FIFTEEN_MINUTES,
        pendingIntent); 

}catch(Exception e){
   e.printStackTrace();
}

А потім ви отримуєте ці трансляції через приймач широкомовної програми. Зауважте, що для цього потрібно буде зареєструвати ефір у вашому маніфесті заявки або за допомогою context.registerReceiver(receiver,filter);методу. Для отримання додаткової інформації про широкомовні приймачі зверніться до офіційних Документів. Транслятор трансляції .

public class MyReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) 
    {
         //do stuffs
    }
}

Якщо це = <10 хвилин → я б пішов з обробником.

Handler handler = new Handler();
int delay = 1000; //milliseconds

handler.postDelayed(new Runnable(){
    public void run(){
        //do something
        handler.postDelayed(this, delay);
    }
}, delay);

3
Чому різні пропозиції залежно від затримки часу?
Саймон Форсберг

7
Ефективність. У документах AlarmManager вказується, що його не слід використовувати для жодного невеликого повторюваного інтервалу.
Jug6ernaut

9
@ SimonAndréForsberg в документах AlarmManager вказує, що Handler - це вподобаний і більш ефективний метод, який можна використовувати для коротких кліщів: "Примітка. Менеджер сигналізації призначений для випадків, коли ви хочете, щоб ваш додаток працював у певний час, навіть якщо ваш програма зараз не працює. Для звичайних операцій з тимчасовим часом (тики, тайм-аути тощо) використовувати простір і набагато ефективніше ".
FoamyGuy

Але мені потрібно запустити метод у тій самій діяльності, яка запустила AlarmManager. Як я можу це зробити?
VansFannel

2
@ahmadalibaloch зсередини, яку ви можете виконати h.removeCallbacks(this);, інакше вам потрібно зберегти посилання на прогон, щоб мати можливість його видалити. Якщо бажано друге, спосіб розміщення тут може бути не найкращим маршрутом.
Jug6ernaut

101

Використовуйте таймер на кожну секунду ...

new Timer().scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        //your method
    }
}, 0, 1000);//put here time 1000 milliseconds=1 second

Я оновив питання з деталями про те, що намагаюся зробити.
VansFannel

4
Не використовуйте таймер ( mopri.de/2010/timertask-bad-do-it-the-android-way-use-a-handler ), використовуйте Handler або ScheduledThreadPoolExecutor.
AppiDevo

69

Ви можете спробувати цей код, щоб викликати обробник кожні 15 секунд через onResume () і зупинити його, коли активність не видно, через onPause ().

Handler handler = new Handler();
Runnable runnable;
int delay = 15*1000; //Delay for 15 seconds.  One second = 1000 milliseconds.


@Override
protected void onResume() {
   //start handler as activity become visible

    handler.postDelayed( runnable = new Runnable() {
        public void run() {
            //do something

            handler.postDelayed(runnable, delay);
        }
    }, delay);

    super.onResume();
}

// If onPause() is not included the threads will double up when you 
// reload the activity 

@Override
protected void onPause() {
    handler.removeCallbacks(runnable); //stop handler when activity not visible
    super.onPause();
}

5
Це те, що я шукав. Ідеально.
гадюка

3
ось ідеальний відповідь!
Riddhi

Пляма на! Використання для перевірки поточної вибраної вкладки MainActivitys у TabLayout відповідає цьому фрагменту, а якщо не припиняє роботу - оскільки onPause () не вдається, коли будь-яка TabLayout вибрала вкладки з обох сторін цієї вибраної вкладки
BENN1TH

досконалий. Це те, що я шукав :) 1 питання, чи можна назвати цей метод з іншого заняття. Або якщо я скористаюся цією діяльністю, цей об’єкт буде знищений? Що робити, якщо я створять статичний обробник і працює. Це можливо?
гіперкодер

17

Якщо ви знайомі з RxJava, ви можете використовувати Observable.interval (), який є досить акуратним.

Observable.interval(60, TimeUnits.SECONDS)
          .flatMap(new Function<Long, ObservableSource<String>>() {
                @Override
                public ObservableSource<String> apply(@NonNull Long aLong) throws Exception {
                    return getDataObservable(); //Where you pull your data
                }
            });

Мінус цього полягає в тому, що вам доведеться архітектором опитувати свої дані по-іншому. Однак, існує багато переваг способу реактивного програмування:

  1. Замість того, щоб контролювати свої дані за допомогою зворотного дзвінка, ви створюєте потік даних, на який ви підписалися. Це розділяє занепокоєння логікою "опитування даних" та "заповненням інтерфейсу користувача вашими даними", щоб ви не змішували код "джерела даних" та свій код інтерфейсу.
  2. За допомогою RxAndroid ви можете обробляти нитки лише у двох рядках коду.

    Observable.interval(60, TimeUnits.SECONDS)
          .flatMap(...) // polling data code
          .subscribeOn(Schedulers.newThread()) // poll data on a background thread
          .observeOn(AndroidSchedulers.mainThread()) // populate UI on main thread
          .subscribe(...); // your UI code

Перевірте RxJava. Він має високу криву навчання, але це зробить обробку асинхронними дзвінками в Android набагато простішим та чистішим.


4

З Котліном ми тепер можемо зробити для цього загальну функцію!

object RepeatHelper {
    fun repeatDelayed(delay: Long, todo: () -> Unit) {
        val handler = Handler()
        handler.postDelayed(object : Runnable {
            override fun run() {
                todo()
                handler.postDelayed(this, delay)
            }
        }, delay)
    }
}

А для використання просто виконайте:

val delay = 1000L
RepeatHelper.repeatDelayed(delay) {
    myRepeatedFunction()
}

3
    new CountDownTimer(120000, 1000) {

        public void onTick(long millisUntilFinished) {
            txtcounter.setText(" " + millisUntilFinished / 1000);

        }

        public void onFinish() {

            txtcounter.setText(" TimeOut  ");
            Main2Activity.ShowPayment = false;
            EventBus.getDefault().post("go-main");

        }

    }.start();

4
Не публікуйте лише відповідь. Будь ласка , змініть свій відповідь і додати деякі пояснення.
Шашант

2

Тут я використовував потік у onCreate () активність повторно, таймер не дозволяє все в деяких випадках Thread - це рішення

     Thread t = new Thread() {
        @Override
        public void run() {
            while (!isInterrupted()) {
                try {
                    Thread.sleep(10000);  //1000ms = 1 sec
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {

                            SharedPreferences mPrefs = getSharedPreferences("sam", MODE_PRIVATE);
                            Gson gson = new Gson();
                            String json = mPrefs.getString("chat_list", "");
                            GelenMesajlar model = gson.fromJson(json, GelenMesajlar.class);
                            String sam = "";

                            ChatAdapter adapter = new ChatAdapter(Chat.this, model.getData());
                            listview.setAdapter(adapter);
                           // listview.setStackFromBottom(true);
                          //  Util.showMessage(Chat.this,"Merhabalar");
                        }
                    });

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    t.start();

У випадку, якщо це знадобиться, його можна зупинити

@Override
protected void onDestroy() {
    super.onDestroy();
    Thread.interrupted();
    //t.interrupted();
}

опишіть, будь ласка, ситуацію, коли моя відповідь не вийде
Умар Ата

Привіт Умаре. Мені потрібен круг увесь час, щоб ця програма жива, Хендлер перетворив повторення в живі, поки активність активна, але мені потрібне коло, коли я також міг відвідувати інші види діяльності. Отже, нитка є рішенням таким чином, щоб переконатися, що вона також має свою боротьбу.
Сем

1

Тут може бути корисна відповідь на вашу проблему використання Rx Java та Rx Android .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.