In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/03 Report--
Handler is an asynchronous callback mechanism provided in Android, which can also be understood as a message mechanism between threads. In order to avoid ANR, we usually put some time-consuming operations (such as network request, Igamo operation, complex calculation, etc.) into the child thread, and when the child thread needs to modify the UI, the child thread needs to notify the main thread to complete the operation of modifying the UI, so we need to use the Handler mechanism to complete the communication between the child thread and the main thread.
1. General steps for using Handler
After clarifying the premise that only the main thread in Android can modify the UI interface and the child threads perform time-consuming operations, let's learn the steps of using Handler.
Create an instance of Handler in the main thread and override the handlerMessage method.
Private Handler handler = new Handler () {@ Overridepublic void handleMessage (Message msg) {switch (msg.what) {case 1: / / execute the operation of modifying UI break;}
Get the Handler object in the child thread and use handler to send messages where update UI operations need to be performed
Message msg = Message.obtain (); msg.obj = "content"; msg.what = 1 send a message to Handlerhandler.sendMessage (msg); in Switch in the handlerMessage method, perform relevant operations according to different constants under case
The above is only one way to use Handler, because the focus of this article is to explore the principle of Handlerde, so other ways of use here do not focus on.
two。 Responsibilities of important categories
Before delving into the principles of the Handler mechanism, we should clarify the responsibilities of several important classes in the Handler mechanism.
Handler: responsible for sending and processing messages MessageQueue: message queue, responsible for storing messages Message: specific messages sent Looper: responsible for looping out messages to Handler processing ThreadLocal: used for data isolation between threads, storing their corresponding Looper3 in each thread. Principle of Handler mechanism
Each Handler is associated with a message queue, which is encapsulated in a Looper object, and each Looper is associated with a thread. In this way, Handler, message queue, and thread are associated.
Handler is a message processor that sends messages to a message queue, which is then taken out of the message queue one by one by the corresponding thread and executed.
By default, there is only one message queue, the main thread's message queue, which is created by the Looper.prepareMainLooper () method, and finally executes Looper.loop () to cycle through the message.
The above description may be a little empty, let's understand it with the source code:
3.1 how does Handler correlate message queues and threads?
Let's first look at the default constructor of Handler:
Public Handler (Callback callback, boolean async) {/ / Code omit mLooper = Looper.myLooper (); / / get Looper if (mLooper = = null) {throw new RuntimeException ("Can't create handler inside thread that has not called Looper.prepare ()");} mQueue = mLooper.mQueue;// get message queue mCallback = callback; mAsynchronous = async through Looper object } / / get Looper object public final Looper getLooper () {return mLooper;}
From the constructor of Handler, we can see that Handler gets a Looper object through Looper.getLooper () while initializing, associates it with Looper, and then gets the message queue through the Looper object. Let's move on to the Looper source to see how Looper.getLooper () is implemented.
/ / initialize the current thread Looper public static void prepareMainLooper () {prepare (false); synchronized (Looper.class) {if (sMainLooper! = null) {throw new IllegalStateException ("The main Looper has already been prepared.");} sMainLooper = myLooper () }} / / set a Looper private static void prepare (boolean quitAllowed) {if (sThreadLocal.get ()! = null) {throw new RuntimeException ("Only one Looper may be created per thread");} sThreadLocal.set (new Looper (quitAllowed)) for the current thread;}
You can see from the above program that through prepareMainLooper (), then call the prepare (boolean quitAllowed) method to create a Looper object, and set the object to sThreadLocal through the sThreadLocal.set (new Looper (quitAllowed)) method.
/ / obtain Looper public static @ Nullable Looper myLooper () {return sThreadLocal.get ();} through ThreadLocal
Through the preparatory work in Looper, a Looper object has been stored in sThreadLocal, and then the myLooper () method gets the Looper through the sThreadLocal.get () method. Then the message queue is associated with the thread, so each thread can only access its own message queue.
To sum up, we can find that message queues are associated with threads through Looper, and Looper is associated with Handler, so Handler is associated with threads and thread message queues.
3.2 how do I perform a message loop?
After the Looper object is created, how are messages sent through Handler processed after they are placed in the message queue? This involves a message loop, which is established through the Looper.loop () method. The source code is as follows:
/ / execute message loop public static void loop () {final Looper me = myLooper (); if (me = = null) {throw new RuntimeException ("No Looper; Looper.prepare () wasn't called on this thread.");} final MessageQueue queue = me.mQueue;// get message queue / / code omit for (;;) {/ / endless loop Message msg = queue.next () / / get the message if (msg = = null) {/ / No message indicates that the message queue is quitting. Return;} / / Code omit try {msg.target.dispatchMessage (msg); / / distribute message} finally {if (traceTag! = 0) {Trace.traceEnd (traceTag);}} / / Code omit msg.recycleUnchecked (); / / message recovery}}
As we can see from the source code, the loop () method is essentially the process of getting messages from the message queue through an endless loop, and then processing the messages again and again.
3.3message processing mechanism msg.target.dispatchMessage (msg); / / distribute messages
Let's start with the dispatchMessage () method in loop, see who is the caller of this method, and go deep into the Message source code to see the specific type of target:
Public final class Message implements Parcelable {/ / Code ellipsis / * package*/ int flags; / * package*/ long when; / * package*/ Bundle data; / * package*/ Handler target; / * package*/ Runnable callback; / * package*/ Message next; / / Code ellipsis}
We can see from the source code that target is actually a Handler type. So Handler sends the message to the message queue for temporary storage, and then sends the message to the Handler itself for processing. Let's move on to the Handler source code to see how Handler handles messages:
Public void dispatchMessage (Message msg) {if (msg.callback! = null) {handleCallback (msg);} else {if (mCallback! = null) {if (mCallback.handleMessage (msg)) {return;}} handleMessage (msg);}}
Private static void handleCallback (Message message) {message.callback.run ();}
/ * Subclasses must implement this to receive messages. * message handling method is an empty method, and the subclass implements * / public void handleMessage (Message msg) {}
As you can see from the source code above, dispatchMessage (Message msg) is only responsible for distributing Message. From the Message source code, we can know that callback is the Runnable type, if the callback is not empty, then execute the handleCallback method to deal with it, and the method will call callback.run (); if the callback is empty, then call handleMessage to process the message, and the method is empty, so we will rewrite the method in the subclass and write the code to modify the UI in it. These two situations occur because Handler sends messages in two forms:
In the general usage steps of this article, I use sendMessage (msg) to send messages, and callback is empty. When using post to send a message, callback is not empty.
The above is the principle of the Handler mechanism, which can be summarized as follows: in the child thread, Handler sends the message to MessageQueue, then Looper constantly reads the message from MessageQueue, and calls Handler's dispatchMessage to send the message, and finally Handler to process the message. To help you understand better, I have drawn a schematic diagram of the Handler mechanism:
The following points are added to the Handler mechanism:
Handler uses the message pool to create messages. When creating messages, it will first query whether there are any message objects from the message pool. If so, use the objects in the message pool directly. If not, create a new message object. The purpose of using ThreadLocal is to ensure that each thread creates only a unique Looper. Later, when other Handler initializes, you directly get the Looper created by the first Handler.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.