Hanlder

1. The implementation principle of Handler

From four aspects Hanlder , Message , MessageQueue , Looper ;
Handler : Responsible for sending and processing messages;
Message : Message object, similar to a node of the linked list;
MessageQueue : Message queue, used to store the data structure of the message object;
Looper : The processor of the message queue (for polling the message object of the message queue);
When the Handler sends a message, it calls the enqueueMessage of the MessageQueue to insert a message into the MessageQueue, and the Looper continuously polls and calls the next method of the MessageQueue. If there is a message, it calls the dispatchMessage of the handler , dispatchMessage is called successfully, and then handlerMessage() is called.

2. Why can't Hanlder be listed in the sub-thread, but the main thread can

Because in the construction method of Handler, the looper object will be obtained through Looper.myLooper(). If it is empty, an exception will be thrown. The main thread has obtained this object through Looper.prepareMainLooper() in the main method of the ActivityThread at the entrance. , and open the loop through Looper.loop(). If you want to use the handler in the child thread, you can first obtain the looper object through Looper.prepare, and use Looper.loop() to open the loop

3. The cause of the memory leak caused by Handler and its solution

1. The non-static inner class and anonymous inner class in java will implicitly hold the external reference of the current class
2. Use the non-static inner class to initialize a Handler in the Activity, and the Handler will hold the reference of the current Activity.
3. If an object is recycled, the premise is that it is not referenced by any other object, so when the Activity page is closed, there is a reference relationship; if there are unprocessed messages/processing messages in the Handler message queue, the Activity will not is recycled, resulting in memory leaks;
solution:
1. Set the subclass of Handler as a static inner class, and use WeakReference weak reference to hold the Activity instance
2. When the outer class ends its life cycle, clear the message queue in Handler

4. A thread can have several Handlers, several Loopers, and several MessageQueue objects

A thread can have multiple Handlers, only one looper, one MessageQueue object. Known in the Looper.prepare() function. Create a Looper object in Looper's prepare method, put it into ThreadLocal, and get the looper object through ThreadLocal. ThreadLocal maintains a ThreadLocalMap class inside. ThreadLocalMap uses the current Thread as the key, so you can know A thread can only have one Looper object at most. A MessageQueue object is created in the Looper constructor and assigned to the mQueue field. Because there is only one Looper object, there must be only one MessageQueue object.

5. What is the data structure of MessageQueue

The internal storage structure is not a real queue, but a single-linked list data structure is used to store the message list, which is a bit different from the traditional queue. The main difference is that the messages in the Android queue are stored in chronological order. , the earlier the message, the closer to the head of the queue. It's a bit of first-in first-out, based not on who enters the queue first, but on the time when the message is to be sent.

6. Why does the Android system not recommend sub-threads to access the UI

There can be multiple sub-threads in Android, but if each sub-thread can access the UI, the interface will become confusing, and multiple threads operating the same resource will cause thread safety issues. Of course, when thread safety issues need to be solved, Our first thought may be to lock, but locking will reduce operating efficiency, so for the sake of Android performance, locking is not used to control UI operations.

7. Can sub-threads update the UI?

Refreshing the UI will call ViewRootImpl.Android every time the UI is refreshed, the final root layout ViewRootImpl.checkThread() to check whether the thread is the creation thread of the View. For the first Divan created by VIewRootImpl, handleResumeActivity will be called first from the Activity declaration cycle, that is to say, ViewRootImpl will be created after onResume. At this time, the UI cannot be accessed in the child thread, and the above child thread is delayed for a while. , handleResumeActivity has been called, so there is a crash, it is okay to directly set the crash-free thread in creae without delay to update the UI, but you can only update the View you created;

8. How to implement thread switching through Handler

When the handler is created in the A thread, a MessageQueue is created in the Looper at the same time. The looper calls the loop in the A thread to enter an infinite for loop to get the message from the MessageQueue. When the B thread calls the handler to send a message, it will pass msg .target.dispatchMessage(msg); insert the message into the MessageQueue corresponding to the handler, Looper finds that a message is inserted into the MessageQueue, then takes out the message and executes the corresponding logic, because Looper.loop() is started in the A thread, so Then it will reach the A thread, achieving the purpose of switching from the B thread to the A thread.

9. The connection between ANR and Handler

Handler is the communication mechanism between threads. In Android, time-consuming operations such as network access and file processing must be executed in sub-threads, otherwise it will cause ANR exception: Application Not Response The reason for ANR exception: in The main thread has performed a time-consuming operation. For an Activity, blocking the main thread for 5 seconds will cause an ANR exception. For BroadcastReceiver, blocking the main thread for 10 seconds will cause an ANR exception. Solution to ANR exception: Time-consuming operations are all performed in sub-threads, but it is not allowed to modify UI in sub-threads, so it is necessary to use Handler to modify UI requirements in sub-threads.

10. How Looper is associated with Thread

Looper and Thread are associated through ThreadLocal. This can be seen in the Looper.prepare() method. There is a sThreadLocal static field of ThreadLocal type in Looper. Looper assigns and retrieves values ​​​​through its get and set methods. Since ThreadLocal is thread-bound, as long as we bind Looper to ThreadLocal, then Looper and Thread will also be associated.

Guess you like

Origin blog.csdn.net/u013290250/article/details/127633809