What is Handler used for?
1) Execute planned tasks, you can perform certain tasks at a predetermined time, and you can simulate a timer
2) Inter-thread communication. When Android's application starts, a main thread will be created, and the main thread will create a message queue to process various messages. When you create a child thread, you can get the Handler object created in the parent thread in your child thread, and you can send messages to the parent thread's message queue through the object. Since Android requires the interface to be updated in UI threads, the interface can be updated in other threads through this method.
For performance optimization reasons, Android's UI operations are not thread-safe, which means that if multiple threads operate UI components concurrently, it may lead to thread-safe issues. To solve this problem, Android has formulated a simple rule: only UI threads are allowed to modify UI components in the Activity.
When a program is started for the first time, Android will start a main thread at the same time. The main thread is mainly responsible for handling UI-related events, such as user key events, user contact screen events, and screen drawing events, and distribute related events to corresponding components for processing. Therefore, the main thread is usually called a UI thread.
Android's messaging mechanism is another form of "event processing". This mechanism is mainly to solve the multi-threading problem of Android applications. The Android platform only allows UI threads to modify the UI components in the Activity, which will cause the newly started threads to be unable to dynamically change the attribute values of the interface components. However, in actual Android application development, especially in game development involving animation, newly launched threads need to periodically change the attribute value of interface components, which needs to be achieved by using Handler's messaging mechanism.
Introduction to Handler class
The Handler class has two main functions:
1. Send a message in the newly started thread.
2. Get and process messages in the main thread.
In order for the main thread to "timely" process the messages sent by the newly started thread, it can obviously be achieved through callbacks - the developer only needs to rewrite the method of processing messages in the Handler class. When the newly started thread sends a message, the message will be sent to the associated MessageQueue, and the Handler will continuously obtain and process messages from the MessageQueue - this will cause the method of processing messages in the Handler class to be called back.
The Handler class contains the following methods for sending and processing messages.
1. void handleMessage(Message msg): Method for processing messages. This method is usually used to be rewritten.
2. Final boolean hasMessages(int what): Check whether the message queue contains the what attribute as a specified value message.
3. Final boolean hsaMessages(int what,Object object): Check whether the message queue contains messages with the what attribute is the specified value and the object attribute is the specified object.
4. Multiple overloaded Message obtainMessage(): Get the message.
5. sendEmptyMessage(int what): Send empty message.
6. Final boolean sendEmptyMessageDelayed(int what, long delayMills): Specify how many milliseconds to send an empty message.
7. Final boolean sendMessage(Message msg): Send the message immediately.
8. Final boolean sendMessageDelayed(Message msg, long delayMillis): Specify how many milliseconds to send a message.
With the above methods, the program can conveniently use the Handler class for messaging.
How Handler, Loop, MessageQueue works
In order to better understand how Handler works, let me first introduce several components that work with Handler.
1. Message: The message object accepted and processed by Handler
2. Looper: Each thread can only have one Looper. Its loop method is responsible for reading messages in MessageQueue, and after reading the message, it handes the message to the Handler that sends the message for processing.
3. MessageQueue: Message queue, which uses a first-in-first-out method to manage Messages. When a program creates a Looper object, it creates a Looper object in its constructor. The constructor source code provided by Looper is as follows:
private Looper() { mQueue=new MessageQueue(); mRun=true; mThread=(); }
This constructor uses private modification, indicating that programmers cannot create Looper objects through the constructor. It is not difficult to see from the above code that the program will create a MessageQueue associated with it when initializing Looper, and this MessageQueue is responsible for managing messages.
1. Handler: It has two functions: sending messages and processing messages. The program uses Handler to send messages. The message sent by the Handler must be sent to the specified MessageQueue. That is, if you want the Handler to work properly, you must have a MessageQueue in the current thread, otherwise the message will not be saved. However, MessageQueue is managed by Looper. That is to say, if you want the Handler to work normally, you must have a Looper object in the current thread. In order to ensure that there are Looper objects in the current thread, you can handle it in the following two situations.
1. In the main UI thread, the system has initialized a Looper object, so the program can directly create a Handler, and then send messages and process messages through the Handler.
2. The programmer starts the child thread by himself. The programmer must create a Looper object by himself and start it. Create a Looper object and call its prepare() method.
The prepare() method ensures that each thread has at most one Looper object. The source code of prepare() method is as follows:
public static final void prepare() { if(()!=null) { throw new RuntimeException("Only one Looper may be createed per thread"); } (new Looper()); }
Then call Looper's static loop() method to start it. The loop() method uses a dead loop to continuously retrieve messages in the MessageQueue and distributes the retrieved messages to the corresponding Handler for processing.
In summary, the functions of Looper, MessageQueue, and Handler are as follows:
1. Looper: Each thread has only one Looper, which is responsible for managing MessageQueue and will continuously retrieve messages from MessageQueue. And distribute the message to the corresponding Handler for processing.
2. MessageQueue: Looper is responsible for managing. It uses a first-in-first-out approach to managing Messages.
3. Handler: It can send messages to the MessageQueue managed by Looper and is responsible for processing the messages assigned to it by Looper.
The steps to use Handler in a thread are as follows:
1. Call Looper's prepare() method to create a Looper object for the current thread. When creating a Looper object, its constructor will create a matching MessageQueue.
2. After having Looper, create an instance of the Handler subclass and override the handlerMessage() method, which is responsible for processing messages from other threads.
3. Call Looper's loop() method to start Looper.
The above is the Handler messaging mechanism in Android introduced to you by the editor. I hope it will be helpful to everyone!