开发者

Android timer/timertask causing my app to crash?

开发者 https://www.devze.com 2023-03-12 08:18 出处:网络
Just testing out a simple block of code in my mainActivity\'s onCreate: Timer timer2 = new Timer(); TimerTask testing = new TimerTask() {

Just testing out a simple block of code in my mainActivity's onCreate:

Timer timer2 = new Timer(); 
        TimerTask testing = new TimerTask() {
            public void run() { 
                Toast.makeText(m开发者_开发技巧ainActivity.this, "test", Toast.LENGTH_SHORT).show();

            }
        };
        timer2.schedule(testing, 1000);

I get the "force close" error though.

What gives?


Alright for anyone else who runs into this, I fixed the problem by using a Handler and Runnable to do the Toast, which seems to be needed for UI interaction:

    final Handler handler = new Handler(); 
    Timer timer2 = new Timer(); 
    TimerTask testing = new TimerTask() {
        public void run() { 
            handler.post(new Runnable() {
                public void run() {
                    Toast.makeText(mainActivity.this, "test", Toast.LENGTH_SHORT).show();
                }

            });


        }
    };
    timer2.schedule(testing, 1000);

I still don't understand why this is necessary though, perhaps someone could explain? But hey at least this code works lol.


Timer(Tasks) are bad! Do it the Android way: Use a Handler.

As you can see in the code snippet, it’s pretty easy to go that way too:

First we need a Handler that starts the Runnable after 100ms

private Handler handler = new Handler();
handler.postDelayed(runnable, 100);

And we also need the Runnable for the Handler

private Runnable runnable = new Runnable() {
   @Override
   public void run() {
      /* do what you need to do */
      foobar();
      /* and here comes the "trick" */
      handler.postDelayed(this, 100);
   }
};

So the “trick” is to tell the handler at the end to start the Runnable again. This way the runnable is started every 100ms, like a scheduleAtFixedRate() TimerTask! If you want it to stop, you can just call handler.removeCallback(runnable) and it won’t start again, until you tell it to


This exact issue is discussed in this article:

http://developer.android.com/resources/articles/timed-ui-updates.html


The app crashes because you are attempting to access elements of the UI thread (a toast) from a different thread (the timer thread). You cannot do this!

You can get round it by either:

Sending a handler message from the timer thread to the UI thread, and then showing the toast in the UI handler function.

OR

In the timer code run use 'runOnUiThread':

@Override

public void run() 

{

    mainActivity.runOnUiThread(new Runnable() {

        public void run() {

            // Access/update UI here

            Toast.makeText(mainActivity.this, "test", Toast.LENGTH_SHORT).show();

        }

    });

}


@YoungMoney

It works but only the first time... Did you make it display the Toast message every second??

Mine only worked once...

===

Edit: Just realised your last line of code is missing the last value which is how often to repeat.

For anyone else concerned, change this:

timer2.schedule(testing, 1000);

to this:

timer2.schedule(testing, 1000, 2000);

If you want to start the timer in 1 second, and update every 2 seconds.


TimerTask task = new TimerTask() {
    @Override
    public void run() {
        //do something

    }
};

Timer t = new Timer();
t.schedule(task, 2000);
0

精彩评论

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

关注公众号