开发者

Problem getting timer to work after cancelling one iteration and starting another

开发者 https://www.devze.com 2023-02-27 16:18 出处:网络
I am stuck trying to get my timer to work, where I will do one countdown, then go back and do another.

I am stuck trying to get my timer to work, where I will do one countdown, then go back and do another.

So, on the second call to timer.scheduleAtFixedRate I get an IllegalStateException, but I am cancelling the TimerTask not the Timer.

What I want to do is count down twenty seconds, then ten seconds, then repeat, updating a text box each time, to inform the user what they should be doing.

One issue is that the countdown is faster than once/second.

04-22 01:34:57.118: DEBUG/TestHandler1(404): message called:2:null
04-22 01:34:57.709: DEBUG/TestHandler1(404): message called:3:null
04-22 01:34:57.899: DEBUG/TestHandler1(404): message called:4:null
04-22 01:34:58.198: DEBUG/TestHandler1(404): message called:5:null

Here is my exception:

04-22 01:35:48.529: ERROR/AndroidRuntime(404): java.lang.IllegalStateException: TimerTask is scheduled already
04-22 01:35:48.529: ERROR/AndroidRuntime(404):     at java.util.Timer.scheduleImpl(Timer.java:574)
04-22 01:35:48.529: ERROR/AndroidRuntime(404):     at java.util.Timer.scheduleAtFixedRate(Timer.java:530)

Here is the code I used for this attempt. When I tried to use a different timertask for each loop it was even worse behavior, as I put the new TimerTask block just before timer.scheduleAtFixedRate, so I went back to this version.

    handler = new Handler() {
        public void handleMessage(Message msg) {
            counterText.setText((new Date()).toString() + "  "
                    + Integer.toString(cntr));
            System.out.println("handleMessage");
        }
    };

    timertask = new TimerTask() {
        public void run() {
            handler.sendEmptyMessage(0);
            cntr++;
            if (cntr > maxReps) {
                timertask.cancel();
                cntr = 0;
            }
        }
    };
    doneButt开发者_如何学Goon.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
                cntr = 0;
                for (MyClass mclass : input.getLoop()) {
                    labelText.setText(mclass.getName());
                    for (int y = 0; y < 8; y++) {
                        maxReps = 20;
                        timer.scheduleAtFixedRate(timertask, 0, 1000);
                        maxReps = 10;
                        labelText.setText("Rest");
                        timer.scheduleAtFixedRate(timertask, 0, 1000);
                    }
                }
        }
    });

Hopefully someone can point out a simple mistake that I made.

Above is a snippet of my code from the Activity, so I am including just what I think is needed to show where I am having a problem.


Given this article in the dev guide: http://developer.android.com/resources/articles/timed-ui-updates.html and a similar post here: http://cart.kolix.de/?p=1438 , I would suggest you to change the strategy and use handler.postDelayed(this, 2000);

But, specifically to the code, my guess is that it may get cancelled the wrong task. I don't really understand the rationale for having two calls to timer.scheduleAtFixedRate(timertask, 0, 1000); and setting maxReps = 20; first and then maxReps = 10; in the same loop, because the loop will not wait for the task to complete before continuing.

So, you are sending at least 16 calls to timer.scheduleAtFixedRate() and not all may get cancelled at the right time.


After experimenting with various methods, I finally settled on this solution.

In my OnCreate method I had this code, and it would go 20 seconds then exit.

    final Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            String s = msg.getData().getString("counter");
            counterText.setText(s);
            Log.d("Activity.handleMessage", s);
        }
    };

    final Runnable runnable = new Runnable() {
        @Override
        public void run() {
            final long start = SystemClock.uptimeMillis();

            while (true) {
                Message m = new Message();
                Bundle b = new Bundle();
                b.putString("counter", Integer.toString(cntr));
                m.setData(b);
                handler.sendMessageDelayed(m, cntr * 1000);
                if (cntr++ == maxReps) {
                    return;
                }
            }
        }
    };

    doneButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            exerciseText.setText(model.getName());
            counterText.setText("0");
            maxReps = 20;
            handler.postDelayed(runnable, 1000);
    });

Part of my difficulty is not thinking about how Android works. I found various approaches that didn't work well.

0

精彩评论

暂无评论...
验证码 换一张
取 消