当前位置:网站首页>Detailed explanation of Android interview notes handler
Detailed explanation of Android interview notes handler
2022-06-25 10:23:00 【HeartCircle】
Android Interview Handler Detailed explanation
1. A thread has several Handler?
There can be multiple Handler Send a message
2. A thread has several Looper ? How to ensure ?
2.1 A thread has several Looper ?
There can only be one , Creating Handler When it's time to specify Looper, The Looper Threads created , Is the thread that processes the message
mMyHandler = new MyHandler(thread.getLooper());
2.2 How to ensure ?
Every thread There is one. ThreadLocal ( Use of the HashMap), For preservation Thread state , Signs, etc Context ( a large number of key-value Key value pair )
2.2.1 How to guarantee a key, only one value?
Hash Algorithm -- Hashcode Guarantee uniqueness
2.2.2 How to ensure Looper Do not modify the ?
stay setLooper I'll check before , Corresponding key Whether the value of is empty , If it's not empty , Throw an exception , Guarantee uniqueness
Looper.java
...
// sThreadLocal yes static final Embellished , Whole app Only one of them , It will only be initialized once
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
...
Looper.prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
sThreadLocal.set(new Looper(quitAllowed)); {
...
map.set(ThreadLocal, looper);
...
}
Because threads only have ThreadLocal, So only one is guaranteed Looper, It also guarantees <sThreadLocal, Looper> The two correspond one by one , And the only
2.3 Looper and MessageQueue What is the relationship ?
MessageQueue Is in Looper For initialization in , And is Final Embellished , Once initialized, it cannot be changed The two correspond one by one
Looper.java
...
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
Summary
Thread -- ThreadLocalMap -- <sThreadLocal, Looper> -- Looper --MessageMessage
==> One Thread only one MessageQueue
==> One Thread only one Looper
3. Handler Cause of memory leak ? Why don't other inner classes say this ?
3.1 Handler Cause of memory leak ?
The inner class holds the outer class object
3.1.1 Why? Handler Will hold external class objects ?
1. because Handler Is created by anonymous inner classes , And in the java in Non static inner class and Anonymous inner class All of them hold references to external classes by default , therefore Anonymous inner class You can use the methods and properties of external classes at will .
2. secondly stay handler.enqueueMessage when ,msg.target = this; send message Hold on to Handler Object reference , and Handler Held by default Activity.this quote , If message Do some time-consuming operations , here Activity Destroyed , So... In the queue Messages waiting to be executed are still held Activity References to .
3. Last Activity Can't be gc Recycling , This leads to a memory leak .
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
Msg == > hold Handler object ==> hold Activity object
eg: If this message is executed after an hour , that msg Will always hold Activity object , Can not be JVM Recycling
3.2 How to solve the leakage problem ?
1. stay Actvitity. onDestroy When , Clear the messages in the message queue
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
2. Use static modification Handler, Soft citation Weak reference
private static MyHandler mMyHandler;
class MyHandler extends Handler {
WeakReference<MainActivity> mContext;
public MyHandler() {
mContext = new WeakReference<>(MainActivity.this);
}
}
3.2.1 static Key role ? Why can we solve the leakage problem ?
Static inner class , Does not hold external class objects
3.3 Why don't other inner classes say this ?
Because other inner classes do not hold Activity object
4. Why can the main thread new Handler? If you want to be in a child thread new Handler What to prepare for ?
4.1 Why can the main thread new Handler?
1. because Android The application will go through... In the startup process ActivityThread.main Method , stay main Method is called Looper.prepareMainLooper(); as well as Looper.loop(); Method to the main thread Handler Of Looper To initialize .
2. So we are In the main thread, you can directly create Handler Use , Instead of initializing Looper The operation of .
4.2 If you want to be in a child thread new Handler What to prepare for ?
need Conduct Looper.prepare as well as Looper.loop(); Call to , And it's initializing Handler When , take Looper Pass in
However, it is not recommended to do this in a child thread new Handler, It is recommended to use HandlerThread, It's sealed
4.2.1 lock
wait and notifyAll:wait-- Release the lock , And wait to be awakened
notifyALl-- Before the notice wait Thread ready for , But it doesn't release the lock , etc. synchronized The code block has been executed , To release
Built in lock ( System built-in lock ): After execution synchronized Code block , from JVM To unlock
synchronized(object)
synchronized(this)
eg1:
HandlerThread1 Two functions in func1,func2
handlerThread1 = new HandlerThread1
In two threads , Separately handlerThread1.func1 and handlerThread1.func2
Conclusion : When a thread 1 perform synchronized(this) When a code block , Threads 2 wait for
func1() {
synchronized(this)
{
///
}
}
func2() {
synchronized(this)
{
///
}
}
eg2: ditto , Put... In two functions synchronized(this) Replace with synchronized(object)
Conclusion : If two threads lock the same object, Are interrelated , otherwise , It does not affect the execution sequence
5. Maintained in a subthread Looper, What is the processing scheme when there is no message in the message queue ? What's the usage? ? What about the main thread ?
When there is no message in the message queue in the child thread , Sleep waiting , If there is no news , Callable Looper.quit, Empty data
5.1 Call not allowed in main thread looper.quit function , Why? ?
Because the main thread uses a lot of Handler Message processing , such as Activity Start of ,UI Interaction , signal communication
5.2 MessageQueue Source code analysis
data structure : Linked list Priority queue
1. When you join the team , Sort by execution time , When the line is full , Blocking , Until the user passes next Get message , notice MessageQueue You can join the team
2. When out of the team ,Looper.loop Start the polling mechanism , When MessageQueue It's empty time , Queue blocking , Wait for the message queue to call enqueueMessage when , The notification queue can fetch messages , Stop blocking
6. Since there can be more than one Handler Go to MessageQueue Add data to ( Every time I send a message Handler May be in a different thread ), So how does it internally ensure thread safety ?
Because in a thread MessageQueue only one , stay en’queueMessage Lock is used in :synchronized(this), Ensure that only one... Can be put into the queue at a time , Guaranteed thread safety
6.1 next When getting the message , Why do I need locks ? It will reduce the message retrieval speed ?
Because to guarantee , When retrieving messages , No other messages are inserted , Get message Follow Insert message You can't At the same time
6.2 performance optimization – Threads
The more threads, the better , Generally, the biggest is cpu In quantity 2 times + 1
Glide Okhttp Each has its own thread pool ? How to optimize ?-- Share the same thread pool ( Use reflection mechanism , Reassign the thread pool of the framework )
7. We use Message How to create it ?
Use obtain, Reuse -- The shared element design pattern is used
Don't exceed 50 A message
If not used obtain, always new message, Can cause Memory jitter ==》GC == 》 Carton
In the custom View in Draw(), Can't be used new, It will also cause the same memory problems
8. Looper Why does a dead cycle not cause the application to get stuck
8.1 since Handler The news is all Loop To the , Why not? ANR problem ?
It was not said that five seconds of non response would occur ANR The problem? ? Why can't sleep for a long time ANR?
produce ANR The reason is not because the main thread is asleep , But because the input event did not respond , If the input event does not respond, you cannot wake up Looper, Just added the five second limit
8.2 Application when there is no message , Is asleep , Release thread , Will not cause the application to jam , Stuck is ANR, and Looper It's sleep
reflection ? Conveyor mode
1. Handler How to cross threads ?
Send message to child thread , The main thread fetches the message
Sub thread :handler.sendMessage-- enqueueMessage-- queue.enqueueMessage( Manage memory )
The main thread :ActivityThread Call in Looper.loop -- queue.next Take out the message -- dispatchMessage Distribution message --handler.handlerMessage
2. Activity Start process
Launcher Click... In the application Our application pictures , start-up zygote, Create a JVM,JVM Going to call ActivityThread Medium main function
2.1 ActivityThread start-up Activity
2.2 root Activity Start sequence diagram
3. Handler Communication mechanism , Is the mechanism for managing memory in threads
4. Synchronization barrier of message mechanism
4.1 If there is an event (message) Must be implemented as soon as possible , that Handler How to ensure the smooth execution of events through message barriers ?
Messages are sorted in order of execution time , Then the message is kept in the queue , So messages can only be taken from the head of the queue . So here comes the question ! What about messages that need urgent treatment ?
It's actually through setting Synchronous barrier to solve
4.2 So what is the synchronization barrier ?
4.2.1 Let's explain first ,Handler in Message It is divided into Sync message Follow Asynchronous messaging , Generally speaking , There is no difference between the two kinds of news , Only when setting The difference only occurs when the barrier is synchronized
4.2.2 commonly Message There will be target, however When setting the synchronization barrier Message No, target, In short , The synchronization barrier is a target Empty Message
4.2.3 This difference is finally reflected in Message.next When , Last code :
Message next() {
//...
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
//...
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) { // Hit the synchronization barrier
// Stalled by a barrier. Find the next asynchronous message in the queue.
// do while Loop through the message linked list
// When you jump out of the loop ,msg Point to the asynchronous message nearest to the header
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
//...
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
// take msg Remove... From the message linked list
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
// Return asynchronous message
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
//...
}
//...
}
}
You can see , If a synchronization barrier is set , Will give priority to target Empty messages ( Asynchronous messaging ), This is considered. Handler A priority mechanism for messages
4.3.4 Set the synchronization barrier
mHandler.getLooper().getQueue().postSyncBarrier();
4.3.5 Synchronous barrier application
Android Application framework for faster response UI Refresh event in ViewRootImpl.scheduleTraversals Synchronous barriers are used in
Reference material
- In Tencent class , Enjoy the courses offered
- Synchronization barrier :https://blog.csdn.net/asdgbc/article/details/79148180
边栏推荐
- 【图像融合】基于形态学分析结合稀疏表征实现图像融合附matlab代码
- Use of Siemens plcs7-200 (I) -- Introduction to development environment and configuration software
- Flask博客实战 - 实现侧边栏文章归档及标签
- clang frontend command failed with exit code 250
- The real difference between i++ and ++i
- Tutorial on installing SSL certificates in Microsoft Exchange Server 2007
- Jetpack compose layout (IV) - constraintlayout
- Gradle download warehouse is slow
- WPF prism framework
- 原生小程序开发注意事项总结
猜你喜欢
Network protocol learning -- lldp protocol learning
Learning notes of rxjs takeuntil operator
我的作文题目是——《我的区长父亲》
我希望按照我的思路尽可能将canvas基础讲明白
Shardingsphere proxy 5.0 sub database and sub table (I)
This is enough for request & response
How much does a small program cost? How much does a small program cost? It's clear at a glance
Modbus协议与SerialPort端口读写
Basic usage and principle of schedulemaster distributed task scheduling center
链表 删除链表中的节点
随机推荐
Flask blog practice - realize the latest articles and search in the sidebar
Exception: gradle task assemblydebug failed with exit code 1
Basic use and cluster construction of consult
On binary tree
Basic use and principle of Minio
Linked list delete nodes in the linked list
WebApi性能优化
Unreal Engine graphics and text notes: use VAT (vertex animation texture) to make Houdini end on Houdini special effect (ue4/ue5)
Modbus protocol and serialport port read / write
How to build a wechat applet? How to open an applet?
我希望按照我的思路尽可能将canvas基础讲明白
【图像融合】基于形态学分析结合稀疏表征实现图像融合附matlab代码
[RPC] i/o model - Rector mode of bio, NiO, AIO and NiO
What is CRA
Flask blog practice - realize personal center and authority management
I'm afraid of the goose factory!
原生小程序开发注意事项总结
虚幻引擎图文笔记:使用VAT(Vertex Aniamtion Texture)制作破碎特效(Houdini,UE4/UE5)上 Houdini端
Guiding principle - read source code
Flask博客实战 - 实现个人中心及权限管理