Android message mechanism - Handler summary

Android message mechanism - Handler summary

Tell me about the Handler principle?

Handler mainly has several roles: Handler, Message, MessageQueue, Looper;

  • When the Handler sends a message, the Message will be stored in the MessageQueue in chronological order;

  • Then Looper continuously takes out messages from the message queue and hands them to Handler for processing

Delay message implementation principle

When the Handler sends a delayed message, it will calculate the time to process the message according to the delayed time, and then insert it into the message queue according to the order of time; when the Looper obtains the message from the message queue, if there is no message to be processed, then It will calculate the execution time of the next delayed message, and call the nativePollOnce method in the message queue. This method will block the current thread and wake up the current thread after the time is set; when the time is up, the thread is woken up, and it will continue to read from the message queue. Take out the message for processing;

The bottom layer of nativePollOnce is implemented through the Epoll mechanism. Epoll is an IO multiplexing model in the linux layer. It monitors the IO status of the FD through registration. When it is readable or writable, it will notify the application layer by calling the registered callback method.

Why does the main thread Looper not ANR?

Because Android is event-driven, Looper needs to process messages in a continuous loop, so that the main thread will not run to the end and cause the APP application process to end;

The ANR is generated because the main thread Looper will send a delayed message before distributing the message. Once the delayed message is executed, an ANR exception will be thrown. When the message is completed within the specified time, the delayed message will be removed, and it will be executed when it times out. And an ANR exception is thrown, so only when the main thread takes too much time to process the message will it cause ANR, and the infinite loop will not cause ANR exception.

And when the message queue is empty, the nativePollonce method will be called to block the current queue, and the current thread will not be woken up until there is a new message or the delayed message time is up

What changes in the postDelay message queue using Handler

The delayed message will calculate the absolute time to finally process the message based on the current time and the delayed time, and then the message queue will insert the newly added message into the appropriate position of the queue according to the order of execution time

What is the Epoll mechanism?

The Epoll mechanism is a mechanism for IO multi-channel concurrency in the Linux system. It registers and monitors the FD file. When the readable and writable status of the FD file changes, it will wake up the blocked application thread and call the callback function to reach the notification. purpose; compared with mechanisms such as poll and socket, it uses a red-black tree to save fd file nodes, which makes it much more efficient to find nodes, and it makes a copy between the user layer and the kernel layer by registering a callback function less

How to ensure multiple handler thread safety?

Handler uses Synchronized to ensure thread safety when sending messages and inserting messages into the message queue

About ThreadLocal, talk about your understanding?

The characteristic of the ThreadLocal variable is that each thread will have an independent object, which is stored in the Thread class of different threads. Its life cycle is as long as the Thread where it is located. Because different threads modify the ThreadLoca variable when they do not change the same object. So there will be no thread safety issues.

The implementation principle of ThreadLocal: When ThreadLocal sets a value, it will first get the ThreadLocalMap object from the current Thread, and then use the current ThreadLocal itself as the key, and the set value as the value, and save it in the ThreadLocalMap, which will be stored in the ThreadLocalMap The key and value are encapsulated into an Entry object, which inherits from the weak reference WeakReference, which can avoid memory leaks; and the Entry object is not saved in the array;

When ThreadLocal gets the value, it also gets the ThreadLocalMap through the Thread class of the current thread, and then uses the current ThreadLocal object as the key to get the corresponding value from the ThreadLocalMap

How to create Message object?

You can obtain objects through the obtainMessage method of Handler or the obtain method of Message. Through these two methods, objects that have been cached can be fully utilized to avoid frequent creation of objects; the Message object itself is a queue implemented by a one-way linked list, using Flyweight Mode, constructing a buffer pool design, when the message is processed, it will be recycled into the buffer pool

Why can't I use java's blocking queue?

Because Android messages not only come from the application layer, but also the native layer of the system will also need to send some messages

Why can't the UI be updated in the child thread?

If the UI can be updated in a sub-thread, then thread safety issues must be dealt with in a multi-threaded environment. Thread synchronization will cause the UI to respond slower and reduce fluency. Therefore, when updating the UI operation in ViewRootImpl, it will first determine whether the current thread is in the main thread. thread, an exception is thrown if it is not

Must the child thread not be able to update the UI?

Not necessarily, because checking whether the UI is updated on the main thread is judged in the ViewRootImpl class, and the ViewRootImpl object is created when the DecorView is added to the WindowManager in the makeVisible method after the onResume method is called, so as long as the ViewRootImpl object is created Previously, sub-threads can update the UI, but it doesn’t make much sense to do so, because the entire interface has not been displayed at this time

What is the solution for maintaining Looper in the sub-thread when there is no message in the message queue?

When there is no message in the message queue, the nativePollOnce method will be called. This method will block the current thread. When a new message comes, or when the delayed message time is up, the underlying epoll mechanism will wake up the current thread, and then Looper will continue. Get the message from the message queue to continue execution

How many loopers does a thread have? How can it be guaranteed, and how many Handlers can there be?

A thread has only Looper, and ThreadLocal is used to ensure that each thread has only one Looper. At the same time, in order to ensure that Looper will not be created repeatedly, when calling Looper.prepare method, it will judge whether Looper has been created. If it has been created, then will throw an exception;

There can be multiple Handlers. When creating a Handler, you can specify which thread Looper to use, which thread Looper to use, and which thread the final message will be executed on.

The reason for the handler memory leak, why do other internal classes not have this problem?

The reason why the Handler leaks memory is because the internal class will refer to the external class by default. For example, if the handler is an internal class when it is created, it will refer to the Activity by default. When the Handler sends a message, the Handler will be held by the Message, and the Message It is held by MessageQueue, MessageQueue is held by Looper, and Looper is held by Thread, so indirectly Activity is also held by Thread thread, and the life cycle of Thread is obviously much longer than Activity. When there are messages in the queue that are not processed Finished, when the Activity needs to exit again, the Activity cannot release resources in time because it is indirectly held by the Thread, resulting in a memory leak; the solution is to declare the Handler as a static inner class, and then return the unprocessed message when exiting Removed, when you need to refer to the Activity, you can use a weak reference to hold it

Why can the main thread new Handler other sub-threads can do it?

By default, other sub-threads cannot directly create a Handler, because the creation of a Handler requires a Looper, and the sub-thread does not create a Looper by default. You need to manually call Looper.prepare to create it before creating a Handler. The reason why the main thread can, It is because when the main thread is just running, the Looper.prepareMainLooper method is called in the ActivityThread to create the Looper of the main thread

Do you understand the producer-consumer design pattern in Handler?

Handler, as a producer, continuously sends messages to the message queue; Looper, as a consumer, continuously takes out messages from the message queue, and finally distributes them to Handler for execution

Since there are multiple Handlers to add data to MessageQueue (each Handler is in a different thread when sending a message), how to ensure internal security

The message queue uses the Synchronized keyword for synchronization to ensure thread safety when adding messages. The implementation of Synchronized uses biased locks, lightweight locks, and heavyweight locks. The heavyweight locks are implemented through Monitor locks.

Is the time of the Delayed message sent by the Handler accurate?

Not necessarily accurate, but basically accurate, there are two main influencing factors:

1. When the nativePollonce thread is blocked, the next wake-up needs to wait for the cpu scheduling to process the delayed message in time, so there may be a certain delay

2. ViewRootImpl will send a synchronization barrier message through the message queue before obtaining the vertical synchronization information through the choreographer and preparing to draw the UI. During the period of returning the vertical synchronization signal, if the delay message we send is not asynchronous, it cannot be immediately To execute, you need to wait for the vertical signal to arrive. After ViewRootImpl sends and processes the asynchronous message, the synchronization barrier will be eliminated; so the delayed message may not be executed on time at this time

Handler synchronization barrier implementation principle

Synchronization barrier refers to inserting a Target==null message into the message queue. When the target is null message is processed, a while loop will be opened to find out whether there is an asynchronous message in the queue to be processed until an asynchronous message is found. The message will jump out of the loop; when we have a message with a higher priority to be processed first, we can insert a synchronization barrier first, and then send an asynchronous message and it will be executed first, but the method of sending a synchronization barrier requires reflection to call

Multiple Handlers send messages; how does Looper know which Handler to send the message to?

When the Handler sends a message, it will save the current Handler to the target variable of the Message. When processing the message, it can directly take out the Handler and process the message;

When Handler processes a message, it will first determine whether CallBack (Runnable) is set in the Message, and if it is set, it will execute and terminate;

If not, judge whether the Handler has set CallBack (Callback), if so, execute it, and judge according to the return value, if it returns true, then terminate;

If it returns false, continue to call back Handler's handleMessage method to continue processing the message

Why Handler can switch threads, how to switch?

The reason why Handler can switch threads is because Looper guarantees that each thread has at most one and only one Looper because of ThreadLocal. When Handler is associated with which thread Looper, all messages sent by Handler will be executed in the thread where Looper is located, so only need Create multiple Handlers and pass in Loopers of different threads to switch.

Why can Looper.loop only be called once in a thread?

Because the Looper.loop method is an infinite loop, when it is called, the code after it has no chance to execute; of course, we can also call Looper.loop multiple times to catch the global exception and restart the message loop to avoid the app being blocked. Kill; the specific method is to send a message through the Handler in the main thread, execute a while loop during message processing, call the Looper.loop method in the loop, and wrap the main with trycatch. When an exception occurs, Looper will call the loop method again Continue to process messages in a loop to avoid app crashes

What is the difference between the Looper of the child thread and the Looper of the main thread?

The looper of the main thread cannot exit, but the Looper of the sub-thread can exit;

The Looper of the main thread is already created in the ActivityThread when the app starts; while the Looper in the sub-thread is not created by default, it needs to actively call the Looper.prepare method to create it

The difference between the method sendMessage and post in Handler?

sendMessage passes in the Message object, and the Post method passes in the Runnable object; the Runnable method passed in by the post method will eventually be saved in the CallBack variable of the Message object

How does Handler send a delayed message?

Handler's postDelayed and sendMessageDelayed can also be used to postAtTime or sendMessageAtTime; in the end, the final execution time will be calculated based on the current time and delay time, and added to the message queue in chronological order

Use Handler to first send a message with a delay of 10s, then send a message with a delay of 5s, then let the main thread sleep for 5s, and finally the sequence of message execution?

After sleep 5 seconds, the message delayed by 5 seconds will be executed immediately, and then after another 5 seconds, the message delayed by 10 seconds will be executed

How to make Handler send a message and let it execute first?

There are two main methods:

1. Put the message at the front of the queue; since the message queue is arranged in chronological order, you only need to send a message and set the execution time to 0.

2. To use a synchronous barrier, first send a synchronous barrier message, then set the message to be asynchronous, and then send an asynchronous message to give priority to execution

What are the similarities and differences between the messages sent by the Handler and the messages sent by the normal Handler during the drawing process of the View?

During the drawing process of View, a vertical synchronization signal will be requested before the ViewRootImpl class starts drawing, and a synchronization barrier message will be sent before the vertical synchronization information is requested; after the vertical synchronization signal is received, an asynchronous message will be sent to start drawing; here Using a synchronization barrier can ensure that asynchronous messages are processed first, so that the UI drawing process will not be delayed by other ordinary synchronous messages; messages sent by ordinary Handlers are all synchronous messages, which will be filtered out by the synchronization barrier

How to judge the current thread is the main thread?

Call Looper.myLooper to obtain the Looper object of the current thread, then call the Looper.getMainLooper method to obtain the Looper of the main thread, and judge whether the two are equal to determine whether it is in the main thread

Guess you like

Origin blog.csdn.net/guangdeshishe/article/details/129963045