当前位置:网站首页>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

 Insert picture description here

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

 Insert picture description here

2.2 root Activity Start sequence diagram

 Insert picture description here

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

  1. In Tencent class , Enjoy the courses offered
  2. Synchronization barrier :https://blog.csdn.net/asdgbc/article/details/79148180
原网站

版权声明
本文为[HeartCircle]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202200544307796.html