Writing download-like functionality into an Activity can cause the Activity to block and remain unresponsive for long periods of time until the page suspends. Therefore, we need to put these time-consuming operations in a separate child thread, and that’s what Handler does.

AD: 51CTO College: IT Boutique Courses online!

One. One question

It’s worth considering that writing download-like functionality into an Activity(the main thread) can cause the Activity to block and remain unresponsive for long periods of time until the page suspends (if it hasn’t finished for 5 seconds). You will receive an Android error saying “force shutdown “). Therefore, we need to put these time-consuming operations in a separate child thread. That’s what Handler is all about. Handler provides asynchronous processing, sending and receiving is not simultaneous (the main thread of the Activity and the thread queue are different threads, parallel, do not affect each other).

2. Introduction of Handler

Handler is a thread communication tool in the Android operating system. It has two main functions :(1) scheduling a message or Runnable to be executed somewhere in the main thread, and (2) scheduling an action to be executed in another thread. Each Handler object maintains two queues (FIFOS), a message queue and a Runnable queue, both provided by the Android operating system. The Handler can be distinguished by the two queues:

  1. Send, receive, and process messages – message queues;
  2. Start, end, hibernate threads – Runnable queues;

To use this Handler, perform the following steps: 1. Create a Handler object. 2. Create Runnable and message. 3. Call the POST and sendMessage methods to add the Runnable and message to the queue.

3. The Runnable queue

1. Threads in Java

In Java, threads can be created in two ways: by inheriting the Thread class and implementing the Runnable interface. The most important thing is to copy the run method to implement the threading function. When the thread runs out of time, it executes the run() function and enters the dead state.

Here’s an example of creating a thread:

Runnable r=new Runnable(){ @Override public void run() { // TODO Auto-generated method stub System.out.println("thread"); handler.postDelayed(thread, 3000); }};Copy the code

2. About Runnable queues

(1) principle

Android’s thread asynchronous processing mechanism: The Handler object maintains a thread queue, and when a new Runnable is sent (post()), it puts it at the end of the queue, and when a Runnable is processed, it takes the Runnable out of the queue head and executes it. When a Runnable is sent to the queue, it is returned immediately, regardless of whether the Runnable was executed, whether it was executed successfully, etc. The execution is performed by the system when the Runnable is queued. It’s like the post office. The sender wrote the letter, put it in the mailbox and went home, not knowing when the mail would be distributed, when it would arrive, or how it would be read. In this way, Android’s asynchronous processing mechanism is implemented.

(2) Specific operation

Add thread to queue:

handler.post(Runnable ); Adds Runnable directly to the queue

Handler. postDelayed(Runnable, long) Add Runnable to the queue after a certain amount of time

Handler. postAtTime(Runnable,long) periodically adds Runnable to the queue

Terminating a thread:

handler.removeCallbacks(thread); Remove Runnable from the Runnable queue

Message queues

1. Message objects

(1) the Message object

The Message object carries data, usually passing messages with arg1,arg2, and of course it can have obj arguments, which can carry Bundle data. It is characterized by very little consumption of system performance.

Initialize: Message MSG =handler.obtainMessage();

(2) Bundle object

Bundles are classes provided by Android that can be thought of as special maps, packages of key-value pairs. In particular, keys and values must be primitive data types or arrays of primitive data types (Map keys and values must be objects). In particular, keys must be strings. Use Message to carry Bundle data:

Add: msg.setdata (Bundle Bundle);

Remove: MSG. GetData ();

2. About message queues

(1) principle

Android’s asynchronous message processing mechanism: The Handler object maintains a message queue. When a new message arrives (sendMessage()), it is placed at the end of the queue and then processed by the main thread’s Handler object (handleMessage()) when the message is queued up. The whole process is also asynchronous, just like Runnable queues.

(2) Specific operations:

Add Runnable: handler.sendMessage(Message) to the queue;

Send the message to message queue msg.sendtoTarget ();

After a certain time delay, send a Message to the Message queue handler. SendMessageDelayed (Message, long);

Regularly sends the Message to the Message queue handler. SendMessageAtTime (long) Message,

Processing messages:

Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler Handler

Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub . . }};Copy the code

Two functions of Handler

1. Schedule the message or Runnable to be executed somewhere on the main thread

Code examples:

public class HandlerTestActivity extends Activity { private Button start; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.handlertest); start=(Button) findViewById(R.id.start); start.setOnClickListener(new startListener()); System.out.println("Activity Thread:"+Thread.currentThread().getId()); } Handler handler=new Handler(); Runnable thread=new Runnable(){ @Override public void run() { // TODO Auto-generated method stub System.out.println("HandlerThread:"+Thread.currentThread().getId()); }}; class startListener implements OnClickListener{ @Override public void onClick(View v) { // TODO Auto-generated method stub handler.post(thread); }}}Copy the code

OnCreate () prints out the ID of the current thread (the main thread). Then click the start button to add the thread to the queue. Thread prints out the ID of the current thread. In this program, we can see that with Handler we can arrange the Runnable to be executed somewhere in the main thread, i.e. function (1).

But there’s a little catch. Have you spotted it? Handler. Post (thread) ¶ This program looks like it implements the async mechanism of Handler. Handler. Post (thread) looks like it implements the function of the newly started thread. Handler.post () doesn’t actually create a new thread, it just executes on the original thread. We’re not implementing async.

2. Schedule an action to be executed in another thread.

(1) The standard way to create threads in Java

The first step:

Runnable r=new Runnable(){ @Override public void run() { // TODO Auto-generated method stub System.out.println("thread"); handler.postDelayed(thread, 3000); }};Copy the code

The second step:

   
Thread t=new Thread (r); 
Copy the code

Step 3:

   
t.start(); 
Copy the code

If handler. Post (thread); We can see that the two ids are different and a new thread is started.

(2) about the stars

The Looper class is used to start a message loop for threads that can loop messages from the message queue, so Looper is essentially a message queue + message loop encapsulation. There is only one Looper per thread. Android threads, except the main thread, do not have Looper enabled by default.

The Handler interacts with the Looper, which can be thought of as an interface to the Looper, sending messages to the specified Looper and defining the Handler. By default, the Handler is bound to its thread’s Looper, that is:

Handler handler=new Handler();等价于Handler handler=new Handler(Looper.myLooper());

Looper has two main approaches:

Looper.prepare(); Enable which stars. The loop (); Let Looper work, fetching messages from the message queue and processing them.

Note: the code written after looper.loop () will not be executed. The function should be a loop inside, and the loop will be aborted when mhandler.getlooper ().quit() is called.

(3) Implementation of Handler asynchronous mechanism

The Handler uses the HandlerThread to separate child threads from the main thread. In fact, a HandlerThread is a special thread that wraps a Looper,

Code examples:

HandlerThread HandlerThread =new HandlerThread("handler_hread"); // Start handlerThread.getlooper () must be called before handlerThread.getlooper () is used, otherwise empty handlerThread.start() is returned; // Bind handler to Looper of handlerThread, Handler =new myHandler(HandlerThread.getLooper ()); class myHandler extends Handler{ public myHandler(){} public myHandler(Looper looper){ super(looper); } @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub System.out.println("Activity Thread:"+Thread.currentThread().getId()); }}Copy the code

Handler.post (); / / the thread ID is printed to indicate that the child thread and the main thread belong to different threads.