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!