当前位置:网站首页>Source code analysis handler interview classic

Source code analysis handler interview classic

2022-06-24 13:35:00 Hua Weiyun

@[TOC](Handler Interview source code analysis interview classic

Preface

stay Android In the middle , In the advanced interview , We are often asked Handler Related knowledge , And the proportion of weight is relatively large , What is this ? Let's take a look at a picture :

 Actually, a mobile phone , It's just one. Handler,

As can be seen from the figure above , Whole APP Startup process : Launcher(APP): zygote -> jvm -> ActivityThread.main()ActivityThread.main() It's us APP Unique main Starting method , As shown in the figure , The green part , Namely Handler A unique space opened up for us , Unique to starting the main thread Looper, Will the current App Independent .

So we can come to a conclusion :Handler It's not just process communication , Process communication is just Handler The auxiliary function of , and Handler The real function of is All the code , It's all in Handler Running in

1、 A thread has several Handler

Examination site

What the interviewer here actually wants to know is , You are right about Handler The cognitive , If the question doesn't come out , Then the interviewer won't ask again .

answer

Before saying the answer , First look, always Handler Execution flow chart of :
 Insert picture description here

From above , We can see that :

  • In a thread , You can create N One of the Handler, Such as hander.sentXXX、 handler.postXX Are creating a Handler. every last message, That is, we insert into the message queue Message node in .

2、 A thread has several Looper? How to ensure

Examination site

What the interviewer here actually wants to know is , You are right about Handler Understanding of process and source code .

answer

  • Before I answer that question , Let's see Handler Execution flow chart of :
    handler -> sendMessage -> messageQueue.enqueueMessage -> looper.loop() -> messasgeQueue.next() -> handler.dispatchMessage() -> handler.handerMessage() ,handler send out message, Get into messageQueue.enqueueMessage queue , Get into looper Middle pass loop Endless loop traversal , Drive the queue forward , after handler.dispatchMessage() Distributed to the handler.handerMessage, So we'll finish the whole Handler technological process , You can also read it wrong directly , In one thread , only one Looper.
  • How to guarantee ?ThreadLocal Multithreading , Storage variables for thread context , Actually ThreadLocal Can't store anything , But in ThreadLocal in , There is one ThreadLocalMap aggregate , What's stored in it <this, value> ,this It's context , Unique ThreadLocal key,key Only , that value It's the only one ,ThreadLocal At creation time , There will be a judgment , If you have already created , Abnormal transactions , So a thread has a unique ThreadLocal There is only one looper. Here's the picture :

ThreadLocal Thread isolation tool class

 Insert picture description here

ThreadLocal Create source code

 Insert picture description here

3、Handler Cause of memory leak ? Why don't other inner classes say this

Examination site

The examiner should want to know , You know GC Recycling JVM Something about it .

answer

ad locum , Let's look at a piece of code first :

    Handler handler = new Handler(){        @SuppressLint("HandlerLeak")        @Override        public void handleMessage(@NonNull Message msg) {            Log.d("tiger", "handleMessage: ");            View view = null;            click(view);            MainActivity2.this.click(view);        }    };    public void click(View view) {            }
  • In the code snippet above handler Code , Monogram yellow , And give a warning : This handler class should be static , Otherwise, a memory leak may occur .
  • So why don't other classes have ?
    Life cycle issues . technological process sendMessage -> sendMessageAtTime -> enqueueMessage stay enqueueMessage in , A piece of code msg.target = this;, It means Message Will hold the current handler,handler Has become massage Part of , If I set up a message to wait 20 Execute in minutes , Then it means , my message Will be waiting 20 It will take minutes to execute ,message hold handler,handler hold (this)activity, This leads to GC It can't be recycled ,JVM Through the reachability algorithm , Tell us , Can't reach , You can't recycle . The life cycle of the inner class , Once held by another lifecycle in the external class lifecycle , Then the external class cannot be released .

4、 Why can the main thread new Handler? If you want to be in a child thread new Handler What to do ?

Examination site

How annoying , I don't know , Why ask for this ?

answer

  • stay APP When it starts , It's just ActivityThread.main() In the method , It was created. looper.loop() , Source code is as follows :
     Insert picture description here
  • So how to in the sub thread new Handler Well ? Just in the child thread , Manually add Looper.prepare(); and Looper.loop(); That's all right. . Look at the following code
    public void click (View view){            new Thread(new Runnable() {                @Override                public void run() {                    Looper.prepare();                    mHandler = new Handler() {                        public void handleMessage(Message msg) {                            // do something()                        }                    };                    Looper.loop();                }            }).start();        }

5、 Maintained in a subthread Looper, What is the processing method when there is no message in the message queue ? What's the usage? ?

Examination site

Master the source code

answer

  • Maintained in a subthread Looper Call... When there is no message quit, You can end the cycle .loop() It's a dead cycle , Want to quit , must msg == null. Please see the source code below :
public static void loop() {        for (;;) {            Message msg = queue.next(); // might block            if (msg == null) {                // No message indicates that the message queue is quitting.                return;            }            msg.recycleUnchecked();        }    }
  • Only when calling quit When , Will return null.
Message next() {        for (;;) {            synchronized (this) {                if (mQuitting) {                    dispose();                    return null;                }            }        }    }void quit(boolean safe) {        synchronized (this) {            if (mQuitting) {                return;            }            mQuitting = true;        }    }
  • So use quit() Wake up the queue , perform loop() Exit loop , Sub thread looper No more execution .

 Insert picture description here

  • The news is on the team : Sort by time , When the queue is full , Blocking , Until the user passes next() Take out the message . When next When the method is called , notice MassageQueue You can join the team .
  • News out of the team : from Looper.loop() Cycle through , Yes queue Polling operation , When the message reaches the execution time, it is taken out , When MessageQueue When it's empty , Queue blocking , Wait for the message to call queue massage When , Notification queue , You can get the message , Stop blocking .
  • handler Blocking queues in multithreading are not used BlockQueue, Because the main thread ( System ) Also in the use of , If you use BlockQueue If you set an upper limit , The system may get stuck .

 Insert picture description here

  • From the above , We can see that ,handler It's a producer - Consumer Design Patterns . So let's see ,looper Two loop blocking modes in :
  1. Execution time blocking ( It's not execution time ),nativePollOnce(long ptr, int timeoutMillis) Perform blocking operation ,timeoutMillis by -1 It means infinite waiting , Until it happens , If 0, No need to wait , Execute now . Please see the source code below :
    Message next() {        final long ptr = mPtr;        if (ptr == 0) {            return null;        }        int nextPollTimeoutMillis = 0;        for (;;) {            nativePollOnce(ptr, nextPollTimeoutMillis);//  The loop enters a blocked state , Wake up after waiting for the execution time             synchronized (this) {                if (msg != null) {                    if (now < msg.when) {                        //  The message is not empty , And it's not time to execute ,nextPollTimeoutMillis  Not for -1                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);                    }                }                // Process the quit message now that all pending messages have been handled.                if (mQuitting) {                    dispose();                    return null;                }            }        }    }
  1. MessagaQueue It's empty , Execution blocking , Waiting to wake up . When inserting a message , Take the initiative to wake up , Please see the source code below :
    Message next() {        if (ptr == 0) { // mPtr==0, Indicates an interrupt loop ,            return null;        }        int pendingIdleHandlerCount = -1;        int nextPollTimeoutMillis = 0;        for (;;) {            nativePollOnce(ptr, nextPollTimeoutMillis);            synchronized (this) {                if (msg != null) {                } else {                    //  No news ,timeoutMillis by -1 It means infinite waiting , Until something happens                     nextPollTimeoutMillis = -1;                }            }        }    }    // mPtr==0    private void dispose() {        if (mPtr != 0) {            nativeDestroy(mPtr);            mPtr = 0;        }    }    //  Wake up the     boolean enqueueMessage(Message msg, long when) {        synchronized (this) {            boolean needWake;            Message p = mMessages;            if (p == null || when == 0 || when < p.when) {                msg.next = p;                mMessages = msg;                needWake = mBlocked;            }            // mPtr != 0  The loop is not interrupted , Wake up operation .            if (needWake) {                nativeWake(mPtr);            }        }        return true;    }

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 ?

Examination site

Thread lock , There will be more synchronized Relevant stuff

answer

  • synchronized lock : synchronized Built in lock , It is from jvm autocomplete , Both insertion and removal require locks , Because at the time of taking , May be inserting . It is the object of the lock , because MessageQueue There is only one in each thread Looper, Every Looper There is only one more MessageQueue.

7、 We use Message How to create it ?

Examination site

Do you want to know if you have ever used ?

answer

  • Creating Message Object time , There are three ways :
  1. Message message = new Message();
  2. Message message1 = Message.obtain(); When looking at the source code , It is found that the internal call is also obtain() Method .
  3. Message message2 = handler.obtainMessage();

8、Looper Why does a dead cycle not cause the application to get stuck

Examination site

Is it ANR The mechanism of ?

answer

  • The application is stuck, which means that ANR, What is ANR?ANR How to detect , got it ANR How to detect , We knew Looper Why does a dead cycle not cause the application to get stuck ?

What is? ANR?

  • ANR This means that the application is unresponsive ,ANR The subject is implemented at the system level . All and ANR Related messages , Will go through the system process (AMS) Dispatch , Then send it to the application process to complete the actual processing of the message , meanwhile , System processes are designed with different timeout limits to track message processing . Once the application processes the message improperly , The timeout limit works , It collects some system state , such as CPU/IO usage 、 Process function call stack , And report whether the user has responded to the process (ANR Dialog box ).

summary

🤩
Originality is not easy. , I also hope you guys can support \textcolor{blue}{ Originality is not easy. , I also hope you guys can support }

give the thumbs-up , Your recognition is the driving force of my creation ! \textcolor{green}{ give the thumbs-up , Your recognition is the driving force of my creation !}

Collection , Your favor is the direction of my efforts ! \textcolor{green}{ Collection , Your favor is the direction of my efforts !}

Comment on , Your opinion is the wealth of my progress ! \textcolor{green}{ Comment on , Your opinion is the wealth of my progress !}

原网站

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