0

How can I invoke method in endless loop that way it would be invoked every 200ms? What I mean is: sendMessage() -> wait(200ms) -> sendMessage -> wait(200ms) and so on, endlessly unless the user decides not to by pushing button. Here is sendMessage method as an example:

private void sendMessage(String message) {
    if (mCommandService.getState() != CommandService.STATE_CONNECTED) {
        Toast.makeText(this, R.string.title_not_connected, Toast.LENGTH_SHORT).show();
        return;
    }
    if (message.length() > 0) {
        byte[] send = message.getBytes();
        mCommandService.write(send);
        mOutStringBuffer.setLength(0);
        mOutEditText.setText(mOutStringBuffer);
    }
}

I can not use Thread.sleep() as it would freeze the UI. Idea with handler.postDelayed() is not viable here aswell I guess. Or maybe it is? How can I achieve that? I can not freeze any of the activities anyhow...

Lisek
  • 753
  • 2
  • 11
  • 31

2 Answers2

4

What you trying to achieve is clearly an async task. Handler or Timer should be your choice. With postDelayed, you need to call the method every time after your task is finish, so scheduleAtFixedRate of your timer should be your pick.

Edit:

Timer timer;
TimerTask task;

and onCreate

timer = new Timer();
task = new Sender();

public startTimer() {
    if(task != null) {
        timer.scheduleAtFixedRate(task, 200);
    }
}
public stopTimer() {
    timer.cancel();
}
private class Sender extends TimerTask {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        if (mCommandService.getState() != CommandService.STATE_CONNECTED) {
            Toast.makeText(this, R.string.title_not_connected, Toast.LENGTH_SHORT).show();
            return;
        }
        if (message.length() > 0) {
            byte[] send = message.getBytes();
            mCommandService.write(send);
            mOutStringBuffer.setLength(0);
            mOutEditText.setText(mOutStringBuffer);
        }
    }

}
Barışcan Kayaoğlu
  • 1,294
  • 3
  • 14
  • 35
  • Could you provide any example, please? Or refer me to your answer anyhow? – Lisek Jan 13 '14 at 13:44
  • `Timer timer = new Timer(); timer.scheduleAtFixedRate(task, 200);` Where task is your TimerTask, or a simple Thread. – Barışcan Kayaoğlu Jan 13 '14 at 13:44
  • But of course, with Timer, you have to control it manually, like timer.cancel(); on pause events or schedule it again on resume. – Barışcan Kayaoğlu Jan 13 '14 at 13:48
  • Is it this: http://stackoverflow.com/questions/2161750/android-controlling-a-task-with-timer-and-timertask good for me to refer to my problem? – Lisek Jan 13 '14 at 13:59
  • Async task is a task that works asynchronously with main UI thread of your activity. Basicly a timer, handler or thread works behind the activity is an async task. They are used for http requests, or tasks that should work separately with the UI thread. Your async tasks should never access your Views. Since you don't access any view objects on your sendMessage, you can use them. You can just create a class extends to TimerTask or Thread and paste your sendMessage method in its run(). Create an object of the class you created and create a timer object. And schedule the timer as i refer before. – Barışcan Kayaoğlu Jan 13 '14 at 14:42
  • 1
    I edited the post and added some example code. But i must warn about one thing. You might wanna use Handler and PostDelayed for this one because, scheduleAtFixedRate will be called every 200 ms even if your task is not completed. This might cause some issues. PostDelayed on the other hand, will be called first and it will be called again at the end of your run() so it will be ensured to get completed. And you might wanna surround your settext() in runOnUIThread(new Runnable(..)); because your UI thread might be busy by the time you set your text and that might cause a crash. – Barışcan Kayaoğlu Jan 13 '14 at 14:48
  • Great thanks. Last two things: 1. `private class Sender` must be provided with external input of `String message`, where to implement that? and 2. If I do it your way, will my program notice that in the meantime of running of this `TimerTask` the `String message` changed and automatically perform changes? What I mean is: `Task` is running with starting `String` in the meantime it changes and system notices the change. – Lisek Jan 13 '14 at 14:55
  • Well since Sender class is an inner class of your main activity class, it should access the message. I was wondering if this could result with duplicated text sends but since you want to call the method every 200 ms, message is changing every 200 ms? Where ever you send the message String as parameter, you can just set the message object of your main activity and the Sender class will keep sending it. – Barışcan Kayaoğlu Jan 13 '14 at 15:02
  • System is meant to send the `String` no matter what the value is. It can send the same `String` for over 30seconds or send complete different each 200ms. Message can be changing even 20 times per seconds, I am supposed to catch one right after the 200ms pass and send it. – Lisek Jan 13 '14 at 15:18
2

Use another thread to run the loop. It should't be running in the Event Dispatch Thread, you could use a SwingWorker object.

Typo
  • 1,875
  • 1
  • 19
  • 32
  • I am fairly new to Android. Right now I have no clue what do you even mean, gonna google I guess. Thanks. – Lisek Jan 13 '14 at 14:01
  • The EDT is the thread where the UI runs, if you put some code to run in the middle it wont be able to draw the changes until the execution ends. – Typo Jan 13 '14 at 14:10
  • So basically, if `String message` changes in the middle of the loop, the method `sendMessage` won't notice this change assuming that I am using `scheduleAtFixedRate`? – Lisek Jan 13 '14 at 14:15
  • No, that's not what I'm saying. What I meant is you can use Thread.sleep(), but not in the EDT. – Typo Jan 13 '14 at 14:20