How to Implement Android timer and removeCallbacks failure

Source: Internet
Author: User

There are many ways to implement the timer. Here I will briefly introduce several methods

(1) Handler + Runnable


[Java]
Handler handler = new Handler ();
Runnable runnable = new Runnable (){

@ Override
Public void run (){
// What you want to do
//......
System. out. println (Thread. currentThread (). getName ());
Handler. postDelayed (runnable, 1000 );
}
};

Handler handler = new Handler ();
Runnable runnable = new Runnable (){
 
@ Override
Public void run (){
// What you want to do
//......
System. out. println (Thread. currentThread (). getName ());
Handler. postDelayed (runnable, 1000 );
}
};
Then call handler. post (runnable); the timer can be started. The thread name is printed every 1 S. From the printing, we can know that it is running in the UI thread instead of opening another thread, to cancel the timer, you only need to call handler. removeCallbacks (runnable.

There is a problem in the above. Sometimes you will find that removeCallbacks sometimes becomes invalid and cannot be removed from the message queue. See the demo below.

 


Figure: two buttons: one is to add Runnable to the message queue and the other is to remove Runnable from the message queue. The Runnable prints logs every 1 second.

 

[Java]
<SPAN style = "FONT-FAMILY: Courier New"> package com. example. demoactivity;
 
Import android. app. Activity;
Import android. OS. Bundle;
Import android. OS. Handler;
Import android. view. View;
Import android. view. View. OnClickListener;
Import android. widget. Button;
 
Public class TimerActivity extends Activity {
Handler handler = new Handler ();
Runnable runnable = new Runnable (){

@ Override
Public void run (){
System. out. println ("update ...");
Handler. postDelayed (runnable, 1000 );
}
};
 
@ Override
Protected void onCreate (Bundle savedInstanceState ){
Super. onCreate (savedInstanceState );
SetContentView (R. layout. timer );

Button mButtonStart = (Button) findViewById (R. id. button1 );
Button mButtonStop = (Button) findViewById (R. id. button2 );

MButtonStart. setOnClickListener (new OnClickListener (){

@ Override
Public void onClick (View v ){
Handler. post (runnable );
}
});

MButtonStop. setOnClickListener (new OnClickListener (){

@ Override
Public void onClick (View v ){
Handler. removeCallbacks (runnable );
}
});
}

} </SPAN> <SPAN style = "FONT-FAMILY: Georgia, 'times new roman ', Times, san-serif">
</SPAN>

Package com. example. demoactivity;

Import android. app. Activity;
Import android. OS. Bundle;
Import android. OS. Handler;
Import android. view. View;
Import android. view. View. OnClickListener;
Import android. widget. Button;

Public class TimerActivity extends Activity {
Handler handler = new Handler ();
Runnable runnable = new Runnable (){

@ Override
Public void run (){
System. out. println ("update ...");
Handler. postDelayed (runnable, 1000 );
}
};

@ Override
Protected void onCreate (Bundle savedInstanceState ){
Super. onCreate (savedInstanceState );
SetContentView (R. layout. timer );

Button mButtonStart = (Button) findViewById (R. id. button1 );
Button mButtonStop = (Button) findViewById (R. id. button2 );

MButtonStart. setOnClickListener (new OnClickListener (){

@ Override
Public void onClick (View v ){
Handler. post (runnable );
}
});

MButtonStop. setOnClickListener (new OnClickListener (){

@ Override
Public void onClick (View v ){
Handler. removeCallbacks (runnable );
}
});
}
 
}
Result:
(1) start-> output-> stop output
(2) start-> output-> Background-> Front-> stop-> continue output

When the Activity enters the background and then enters the foreground for running, removeCallbacks cannot remove updateThread from message queue.
Why?
In the process of switching an Activity from the foreground to the background, the thread is always running, but when the Activity is transferred to the foreground, the Runnable runnable will be redefined; in other words, the runnable removed from the message queue is not the same object as the runnable added to the message queue. If the runnable is defined as static, removeCallbacks will not expire. For static variables, there is only one copy in the memory (memory saving), and the JVM will only allocate the static memory once, complete the memory allocation of static variables during the loading process. We can solve the above problem by making the following changes:


[Java]
Static Handler handler = new Handler ();
Static Runnable runnable = new Runnable (){

@ Override
Public void run (){
System. out. println ("update ...");
Handler. postDelayed (runnable, 1000 );
}
};

Static Handler handler = new Handler ();
Static Runnable runnable = new Runnable (){
 
@ Override
Public void run (){
System. out. println ("update ...");
Handler. postDelayed (runnable, 1000 );
}
}; (2) using Timer


[Java]
Timer timer = new Timer ();
Timer. schedule (new TimerTask (){

@ Override
Public void run (){
System. out. println ("update ....");
}
},0, 1000 );

Timer timer = new Timer ();
Timer. schedule (new TimerTask (){

@ Override
Public void run (){
System. out. println ("update ....");
}
}, 0, 1000); The preceding statement is printed every second. The run method runs in the subthread and cannot directly update the UI operation. Note that timer is called if the operation is canceled. cancel () to remove the task.


(3) Use the Handle and thread sleep (long) Methods

1. Define a Handler class for processing received messages


[Java]
Handler handler = new Handler (){
Public void handleMessage (Message msg ){
Super. handleMessage (msg );
System. out. println ("update ...");
}
}

Handler handler = new Handler (){
Public void handleMessage (Message msg ){
Super. handleMessage (msg );
System. out. println ("update ...");
}
} 2. Create a New Thread class that implements the Runnable interface. Use a boolean to control the start and end of the thread. The boolean isLive = true is as follows:


[Java]
Public class MyThread implements Runnable {
@ Override
Public void run (){
While (isLive ){
Try {
Thread. sleep (1000); // Thread pause for 1 second, in milliseconds
Message message = new Message ();
Message. what = 1;
Handler. sendMessage (message); // send a message
} Catch (InterruptedException e ){
E. printStackTrace ();
}
}
}
}

Public class MyThread implements Runnable {
@ Override
Public void run (){
While (isLive ){
Try {
Thread. sleep (1000); // Thread pause for 1 second, in milliseconds
Message message = new Message ();
Message. what = 1;
Handler. sendMessage (message); // send a message
} Catch (InterruptedException e ){
E. printStackTrace ();
}
}
}
}
3. Add the following statement where the thread needs to be started

 

[Java]
New Thread (new MyThread (). start ();

New Thread (new MyThread (). start (); 4. If it is canceled, set isLive to false.

Today we will mainly introduce these three methods. I hope you can point out what is not well written. Thank you!

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.