Как запустить метод каждые X секунд
Я разрабатываю приложение для Android 2.3.3, и мне нужно запускать метод каждые X секунд.
В iOS у меня есть NSTimer, но в Android я не знаю, что использовать.
Кто-то рекомендовал мне Хендлер; другой порекомендовал мне 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
Это действительно зависит от того, сколько времени вам нужно, чтобы запустить функцию.
Если это = > 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
}
}
Если это = < 10minutes → Я бы пошел с обработчиком.
Handler handler = new Handler();
int delay = 1000; //milliseconds
handler.postDelayed(new Runnable(){
public void run(){
//do something
handler.postDelayed(this, delay);
}
}, delay);
Ответ 2
Используйте Таймер на каждую секунду...
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
//your method
}
}, 0, 1000);//put here time 1000 milliseconds=1 second
Ответ 3
Вы можете попробовать этот код вызывать обработчик каждые 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();
}
Ответ 4
Если вы знакомы с 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
}
});
Недостатком этого является то, что вы должны архивировать опрос своих данных по-другому. Тем не менее, существует много преимуществ для метода реактивного программирования:
- Вместо управления вашими данными через обратный вызов вы создаете поток данных, на которые вы подписываетесь. Это отделяет логику логики "опроса данных" и логику "заполнение пользовательских интерфейсов вашими данными", чтобы вы не смешивали код "источника данных" и код пользовательского интерфейса.
-
С RxAndroid вы можете обрабатывать потоки всего в 2 строках кода.
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 намного проще и чище.
Ответ 5
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();
Ответ 6
Здесь я использовал поток в onCreate() a Activity повторно, таймер не позволяет все в некоторых случаях 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();
}
Ответ 7
С Kotlin мы можем теперь сделать универсальную функцию для этого!
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()
}