如何每隔X秒运行一次方法


114

我正在开发一个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
定义“最好的”。您想以哪种方式做到最好?
西蒙·佛斯伯格

我不知道哪种方法更适合NSTimer。
VansFannel

@VansFannel您要间隔多长时间?
FoamyGuy 2012年

我已用有关我要做什么的详细信息更新了该问题。
VansFannel

这个问题:stackoverflow.com/questions/6242268/…,与此问题类似,并且有很好的答案。
VansFannel

Answers:


168

这实际上取决于您需要运行该功能多长时间。

如果=> 10分钟,则→我将选择Alarm Manager。

// 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
AlarmManager文档中的@SimonAndréForsberg 指出Handler是用于短时间间隔的首选且更有效的方法:“注意:Alarm Manager适用于希望在特定时间运行应用程序代码的情况,即使您应用程序当前未运行。对于正常的计时操作(滴答声,超时等),使用Handler更容易,效率更高。”
FoamyGuy 2012年

但是,我需要在与启动AlarmManager相同的Activity中运行一个方法。我怎样才能做到这一点?
VansFannel

2
您可以从runnable中执行@ahmadalibaloch h.removeCallbacks(this);,否则您需要维护对runnable的引用才能将其删除。如果需要第二个,此处发布的方法可能不是您的最佳选择。
Jug6ernaut


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
那是完美的答案!

发现!用于检查MainActivitys当前在TabLayout中选择的选项卡与该片段匹配,并且如果不停止工作,因为onPause()在此选项卡的任一侧的任何TabLayout选择的选项卡时均会失败
BENN1TH

完善。这就是我一直在寻找的方法:) 1个问题,我可以从另一个活动中调用此方法吗?或者,如果我进行此活动,该对象将被销毁?如果我创建一个静态处理程序并且可运行该怎么办。那可能吗?
hyperCoder

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. 您可以创建订阅的数据流,而不是通过回调控制数据。这将“轮询数据”逻辑和“用数据填充UI”逻辑的关注分开,这样您就不会将“数据源”代码和UI代码混在一起。
  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

使用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()
}

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
不要只张贴代码答案。请编辑您的答案并添加一些说明。
Shashanth

2

在这里,我在Activity的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();
}

请描述当我的答案不起作用时的情况
Umar Ata '18

你好,乌玛。我一直需要一个循环来使该应用程序处于活动状态,在活动仍然存在的情况下,Handler使活动重复进行,但是在我能够访问其他活动的同时,我也需要一个循环。因此线程以这种方式是解决方案,确保它也有自己的挣扎。
山姆

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.