In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly explains "what are the Handler-related interview questions". Interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn what are the Handler-related interview questions.
1. What are the ways to get Message instances? Which is better?
There are two main ways to obtain an Message instance. One is to create it directly, Message msg = new Message. The other is to get a Message object through Message.obtain () or Handler.obtatinMessage (). It is more recommended to use the latter approach, where the resulting object is obtained from the object collection pool and reuses the processed Message object rather than regenerating a new object. Both Message.obtain () and Handler.obtatinMessage () end up calling the obtain () method of the Message class, and if you look at the contents of the method, you'll know that you get Message from the object recycling pool.
Public static Message obtain () {synchronized (sPoolSync) {if (sPool! = null) {Message m = sPool; sPool = m.next; m.next = null; m.flags = 0; / / clear in-use flag sPoolSize--; return m }} return new Message ();}
two。 Is the Message message confusing when Activity has more than one Handler? How can I tell which Handler processes the current message?
There will be no confusion. The message sent by which Handler will be handled by this handler at that time. When sending a message, the target is bound. This target is the Handler itself. When you need handler to call dispatchMessage (msg) to process the message, this Handler is the handler bound when the message is sent.
No matter which method is used to send the message, enqueueMessage (MessageQueue queue, Message msg, long uptimeMillis) will eventually be called to send the message.
Private boolean enqueueMessage (MessageQueue queue, Message msg, long uptimeMillis) {msg.target = this; if (mAsynchronous) {msg.setAsynchronous (true);} return queue.enqueueMessage (msg, uptimeMillis);}
The this here is the current handler. To see which handler to take when you need Handler to process messages, the main source code is posted below.
Public static void loop () {. For (;) {Message msg = queue.next (); / / might block if (msg = = null) {/ / No message indicates that the message queue is quitting. Return;} / / This must be in a local variable, in case a UI event sets the logger. If (traceTag! = 0 & & Trace.isTagEnabled (traceTag)) {Trace.traceBegin (traceTag, msg.target.getTraceName (msg));} final long dispatchStart = needStartTime? SystemClock.uptimeMillis (): 0; final long dispatchEnd; try {msg.target.dispatchMessage (msg); dispatchEnd = needEndTime? SystemClock.uptimeMillis (): 0;} finally {if (traceTag! = 0) {Trace.traceEnd (traceTag);}}. Msg.recycleUnchecked ();}}
This is part of the code when you loop the message, and the code for processing the message is msg.target.dispatchMessage (msg); where target is the handler that sent the message at that time.
3. Send messages in the child thread, but can receive the message in the main thread. How do the main thread and the child thread switch?
The subthread uses handler to send messages, and the messages sent are sent to the MessageQueue associated with the main thread, and the Looper associated with the main thread is also looping messages. Handler is associated with the Looper and MessageQueue of the main thread, so the processing logic of the final message is also in the main thread. Only the message is sent in the child thread, the rest is in the main thread, the Handler is associated with the Looper of which thread, the message processing logic is executed in the associated thread, and the direction of the corresponding message is in the associated MessageQueue. So it's a natural process for a child thread to switch to the main thread, and it's not as complicated as you might think.
4. Can I create a Handler in a child thread?
Yes, but call the prepare () method to create the Looper before creating it. When Handler is created, it checks to see if the Looper is created, and throws an exception if it is not created. The relevant source codes are as follows:
Public Handler (Callback callback, boolean async) {. MLooper = Looper.myLooper (); if (mLooper = = null) {throw new RuntimeException ("Can't create handler inside thread" + Thread.currentThread () + "that has not called Looper.prepare ()");} mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async;}
So we need to first call the prepare () method to create the Looper on the child thread. It is also mentioned here that you do not need to create a Looper yourself when creating the main thread, because it has been created for us in the ActivityTread class, and the relevant source code is as follows:
Public static void main (String [] args) {. Looper.prepareMainLooper (); / / create looper / / Find the value for {@ link # PROC_START_SEQ_IDENT} if provided on the command line for the main thread. / / It will be in the format "seq=114" long startSeq = 0; if (args! = null) {for (int I = args.length-1; I > = 0 -- I) {if (args [I]! = null & & args [I] .startsWith (PROC_START_SEQ_IDENT)) {startSeq = Long.parseLong (args [I] .substring (PROC_START_SEQ_IDENT.length ();} ActivityThread thread = new ActivityThread () Thread.attach (false, startSeq); if (sMainThreadHandler = = null) {sMainThreadHandler = thread.getHandler ();} if (false) {Looper.myLooper (). SetMessageLogging (new LogPrinter (Log.DEBUG, "ActivityThread"));} / / End of event ActivityThreadMain. Trace.traceEnd (Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop (); throw new RuntimeException ("Main thread loop unexpectedly exited");}
Looper.prepareMainLooper (); this code is to create a Looper for the main thread. So by creating a Handler directly in the main thread, you can loop the message directly, because the Android main thread has the Looper ready for us.
5. How many Handler can a thread have? How many Looper?
A thread can have more than one Handler, but only one Looper. Before you create a Handler, you need to create a Looper, otherwise an error will be reported. Instructions have been made in the source code.
Public Handler (Callback callback, boolean async) {. MLooper = Looper.myLooper (); if (mLooper = = null) {/ / determine whether Looper is created throw new RuntimeException ("Can't create handler inside thread" + Thread.currentThread () + "that has not called Looper.prepare ()");} mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async;}
Looking at the creation of Looper, it is in the prepare () method.
/ / sThreadLocal.get () will return null unless you've called prepare (). Static final ThreadLocal sThreadLocal = new ThreadLocal (); 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));}
To determine whether a looper exists before creation, the existence throws an Only one Looper may be created per thread exception, which tells us that a thread can only have one Looper. The role of TreadLocal is to isolate threads, ensuring that a thread corresponds to a Looper. You can also look at the source code of the Looperg constructor
Private Looper (boolean quitAllowed) {mQueue = new MessageQueue (quitAllowed); mThread = Thread.currentThread ();}
The initialization of MessageQueue is in the construction method of Looper. No matter how many Handler a thread has, it is associated with the same Looper and MessageQueue.
There are many questions that can be asked about Handler, and the above are just some of the questions that I think are more important. After looking for the answer, I went through the whole process of the Handler mechanism in my mind and drew a sketch.
The correlation Graph of important classes in Handler Mechanism
The principle of Handler mechanism involves several important classes: Handler, Message, MessageQueue, Looper.
The child thread is used to send a message to the main thread to illustrate the whole process.
First create a Handler in the main thread, create Looper and MessageQueue objects in the Handler class, and assign values in the Handler constructor
Final Looper mLooper; final MessageQueue mQueue; public Handler (Callback callback, boolean async) {. MLooper = Looper.myLooper (); if (mLooper = = null) {throw new RuntimeException ("Can't create handler inside thread" + Thread.currentThread () + "that has not called Looper.prepare ()");} mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async;}
MLooper = Looper.myLooper (); the resulting Looper is the Looper of the main thread
The MessageQueue obtained by mQueue = mLooper.mQueue; is the MessageQueue created in the Looper constructor.
Once the Handler instance is created, we will call handler.sendMessage (msg) on the child thread; send a message and put the message in the MessageQueue. In enqueueMessage (), set the target for each message, and this target is the current handler.
Private boolean enqueueMessage (MessageQueue queue, Message msg, long uptimeMillis) {msg.target = this; if (mAsynchronous) {msg.setAsynchronous (true);} return queue.enqueueMessage (msg, uptimeMillis);}
Then call Looper.loop (); (it has been written for us in ActivityThread's main ()) and start to loop the message. After getting the message, you will use handler to retrieve the message for processing. The key code is msg.target.dispatchMessage (msg). The handler here corresponds to the Handler we set for message at the beginning.
/ * Handle system messages here. * / public void dispatchMessage (Message msg) {if (msg.callback! = null) {handleCallback (msg);} else {if (mCallback! = null) {if (mCallback.handleMessage (msg)) {return;}} handleMessage (msg) }}
Finally, we went to process our message in the handleMessage (msg) of Handler.
This is the whole process of a child thread sending a message to the main thread, with a lot of source code, and I only intercepted some of the key points. One more thing to mention here is threading messages. There are three things you need to do to process messages in a thread
1. First create a Looper (Looper.prepare ()) 2. Then create a Handler, which is associated with the Looper of the current thread by default. Circular message (Looper.loop ())
The order of these three steps cannot be changed. Because the main thread has already created the Looper for us, we don't need to write, but we need to create the Looper on the child thread.
The understanding of the Handler mechanism depends on yourself, constantly looking at the source code, to understand and sort out the mutual calls between them. Only when you have a deeper understanding of Handler can you answer the interviewer's questions in the interview. It is not advisable to rely on rote memorization.
At this point, I believe you have a deeper understanding of "what are the Handler-related interview questions?" you might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
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.