3

Do Java/Android have any constructs available for running a method within a class at some time interval?

I am aware of the Scheduler and Timer classes but I need to avoid instantiating another class. The method must not run in another separate thread. Running an AsyncTask or Handler results in a separate thread.

madth3
  • 7,275
  • 12
  • 50
  • 74
Johann
  • 27,536
  • 39
  • 165
  • 279
  • 1
    you want something run on a schedule on the main() thread? – radai Jan 11 '13 at 15:17
  • 3
    What do you want to achieve. To run a method after a certain time in the same thread? How should this work? – Uwe Plonus Jan 11 '13 at 15:17
  • Yes. Run a method in the same thread but delayed. – Johann Jan 11 '13 at 15:17
  • 2
    apart from a loop sleep()ing and calling your function there's no other way that i know of – radai Jan 11 '13 at 15:18
  • 2
    Why do you have the restrictions "same thread" and "avoid instantiating another class". Doesn't look reasonable to me. – Howard Jan 11 '13 at 15:19
  • use **Thread.sleep(long millis)** – xagyg Jan 11 '13 at 15:20
  • I don't want the thread to sleep. I just want to have a method executed after a time has expired but not block the thread. sleep blocks the thread. – Johann Jan 11 '13 at 15:21
  • AndroidDev If that thread shouldn't sleep, you should delegate the "wait and fire" mechanisum to another thread run in parallel. You can't have the same thread non-blocking and at the same time, execute something after a delay. – asgs Jan 11 '13 at 15:24
  • Yes, I just thought of that as well. Add your comment as the answer and I'll check it off. I'll create and AsyncTask or Runnable and have it call back into the original thread at a time interval and execute the method there. – Johann Jan 11 '13 at 15:26
  • If you want to specifically do this for Android, you could add [tag:Android] as it has additional libraries – Peter Lawrey Jan 11 '13 at 15:30
  • It's for Android. What do you mean "add Android"? – Johann Jan 11 '13 at 15:37
  • Would you mind to accept one of the answers? – gaborsch Jan 18 '13 at 01:19

4 Answers4

1

The method must not run in another separate thread

Because of this requirement you only have one reasonable solution, you must wait in your own thread, like this:

for (int i = 0; i < 100; i++) {
    long intervalInMs = 1000; // run every second
    long nextRun = System.currentTimeMillis() + intervalInMs;
    callAMethod();
    if (nextRun > System.currentTimeMillis()) {
        Thread.sleep(nextRun - System.currentTimeMillis());
    }
}

Note, that if the method call takes longer time than you want to wait, it will not call twice (because you only have one Thread) You can detect it by writing an else clause to the if, and make some modifications (e.g. increase the intervalInMs);

gaborsch
  • 15,408
  • 6
  • 37
  • 48
  • There is rarely "only one solution" to any programming problem. In this case, some kind of polling solution is a possible alternative, although very likely difficult to implement. – Code-Apprentice Jan 11 '13 at 19:43
  • Concerning that he can use only the current Thread, I can hardly imagine any other solution that would make a significant difference. Also, you cannot use other classes, so you can't break up the logic too much. In general, I agree with you. Varietas delectat :) – gaborsch Jan 11 '13 at 19:56
  • I agree that there are unlikely any *reasonable* solutions; however, this is very different than claiming there is only one solution. I posted a suggestion of a possible polling solution. I don't think it's a terribly good solution, necessarily, but it's a possible solution to at least consider. – Code-Apprentice Jan 11 '13 at 20:08
0

You need to use the AlarmManager for this.

Check this SO for a good overview: Android: How to use AlarmManager

I would not try to manage this within your own thread, but let the Android framework handle this for you. Not sure why you need it to run in the same Thread.

Community
  • 1
  • 1
Booger
  • 18,579
  • 7
  • 55
  • 72
0

Create a custom Timer that receives a Listener, then when your time has elapsed, send the callback to the object that has created the Timer in his thread.

This will create a new Thread for the Timer, but the method you want to execute, will be executed on the original's object thread

noni
  • 2,927
  • 19
  • 18
0

If you really must do this in the same thread without blocking, one possible solution is to do some kind of polling. I imagine code which periodically calculates how much time has passed since the last time the method fired. If the configured time period has elapsed, then fire the method again.

This kind of solution seems complex to implement. How often do you execute the polling code? How do you execute the polling code within the logic of the rest of the app that is likely continuing to execute in the mean time? These are only the technical challenges that come immediately to mind. I'm sure there are others. With this in mind, I think the better solution is to rethink your restrictions. Why do you want to do this in the same thread? You should think hard about your reasons and consider using a separate thread (whether you roll it yourself with Timer or you use the Android platform to manage it for you with AlarmManager.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268