"original" Source Angle Analysis Android message mechanism series (V) How--looper works

Source: Internet
Author: User
<span id="Label3"></p><p><p><span style="font-size: 16px; color: #ff0000"><strong>ι <span style="font-size: 12px; color: #999999">Copyright Notice: This article for Bo Master original article, without Bo Master permission not Reproduced. </span></strong></span></p></p><p><p></p></p><p><p>Looper is used for message loops in the Android messaging Mechanism. It will keep looping, go to the MessageQueue to see if there is a new message, and if there is a message, process the message immediately, otherwise wait.</p></p><p><p>There is a property in Looper:</p></p><pre><pre><span style="color: #0000ff">Static</span> <span style="color: #0000ff">Final</span> <span style="color: #0000ff">New</span> Threadlocal<looper> ();</pre></pre><p><p>This explains what we said earlier that we can achieve looper In-thread access through Threadlocal.</p></p><p><p>In addition, there are two attributes to Note:</p></p><pre><pre><span style="color: #0000ff">Final</span> <span style="color: #000000">MessageQueue mqueue;</span> <span style="color: #0000ff">Final</span> Thread mthread;</pre></pre><p><p></p></p><p><p>Let's take a look at the Looper constructor:</p></p><pre><pre> <span style="color: #0000ff">Private</span> Looper (<span style="color: #0000ff">boolean</span> <span style="color: #000000"> quitallowed) { </span><span style="color: #0000ff">new</span> <span style="color: #000000"> MessageQueue (quitallowed); </span> =<span style="color: #000000"> Thread.CurrentThread (); }</span></pre></pre><p><p>In the constructor, a MessageQueue message queue is created and the objects of the current thread are Saved.</p></p><p><p></p></p><p><p>Next look at the loop method, only after the loop method is called, the message circulatory system really played a role.</p></p><pre> <span style="color: #008000"><span style="color: #008000">/**</span></span><span style="color: #008000"><span style="color: #008000">* Run The message queue in this Thread. Be sure to call * {</span></span><span style="color: #808080"><span style="color: #808080">@link</span></span><span style="color: #008000"><span style="color: #008000">#quit ()} to end of the Loop. </span></span><span style="color: #008000"><span style="color: #008000">*/</span></span> <span style="color: #0000ff"><span style="color: #0000ff"></span> public</span> <span style="color: #0000ff"><span style="color: #0000ff">Static</span></span> <span style="color: #0000ff"><span style="color: #0000ff">void</span></span><span style="color: #000000"><span style="color: #000000">Loop () {</span></span><span style="color: #0000ff"><span style="color: #0000ff">Final</span></span>Looper me =<span style="color: #000000"><span style="color: #000000">Mylooper (); </span></span><span style="color: #0000ff"><span style="color: #0000ff">if</span></span>(me = =<span style="color: #0000ff"><span style="color: #0000ff">NULL</span></span><span style="color: #000000"><span style="color: #000000">) { </span></span><span style="color: #0000ff"><span style="color: #0000ff">Throw</span></span> <span style="color: #0000ff"><span style="color: #0000ff">New</span></span>RuntimeException ("No Looper; Looper.prepare () wasn ' t called on the This Thread. "<span style="color: #000000"><span style="color: #000000">); } </span></span><span style="color: #0000ff"><span style="color: #0000ff">Final</span></span>MessageQueue queue =<span style="color: #000000"><span style="color: #000000">me.mqueue; </span></span><span style="color: #008000"><span style="color: #008000">//</span></span><span style="color: #008000">make <span style="color: #008000">sure the identity of the the the the The local process,</span></span><span style="color: #008000"><span style="color: #008000">//</span></span><span style="color: #008000">And keep track of the what, <span style="color: #008000">identity token actually is.</span></span><span style="color: #000000"><span style="color: #000000">binder.clearcallingidentity (); </span></span><span style="color: #0000ff"><span style="color: #0000ff">Final</span></span> <span style="color: #0000ff"><span style="color: #0000ff">Long</span></span>Ident =<span style="color: #000000"><span style="color: #000000">binder.clearcallingidentity (); </span></span><span style="color: #0000ff"><span style="color: #0000ff"></span> for</span><span style="color: #000000"><span style="color: #000000"> (;;) {Message msg</span></span>= Queue.next ();<span style="color: #008000"><span style="color: #008000">//</span></span><span style="color: #008000"><span style="color: #008000">might block</span></span> <span style="color: #0000ff"><span style="color: #0000ff">if</span></span>(msg = =<span style="color: #0000ff"><span style="color: #0000ff">NULL</span></span><span style="color: #000000"><span style="color: #000000">) { </span></span><span style="color: #008000"><span style="color: #008000">//</span></span><span style="color: #008000"><span style="color: #008000">No message indicates that the message queue is Quitting.</span></span> <span style="color: #0000ff"><span style="color: #0000ff">return</span></span><span style="color: #000000"><span style="color: #000000">; } </span></span><span style="color: #008000"><span style="color: #008000">//</span></span><span style="color: #008000">this <span style="color: #008000">must is in a local variable with case a UI event sets the logger</span></span> <span style="color: #0000ff"><span style="color: #0000ff">Final</span></span>Printer logging =<span style="color: #000000"><span style="color: #000000">me.mlogging; </span></span><span style="color: #0000ff"><span style="color: #0000ff">if</span></span>(logging! =<span style="color: #0000ff"><span style="color: #0000ff">NULL</span></span><span style="color: #000000"><span style="color: #000000">) {logging.println (</span></span>">>>>> dispatching to" + msg.target + "" +<span style="color: #000000"><span style="color: #000000">Msg.callback</span></span>+ ": " +<span style="color: #000000"><span style="color: #000000">msg.what); } </span></span><span style="color: #0000ff"><span style="color: #0000ff">Final</span></span> <span style="color: #0000ff"><span style="color: #0000ff">Long</span></span>Tracetag =<span style="color: #000000"><span style="color: #000000">me.mtracetag; </span></span><span style="color: #0000ff"><span style="color: #0000ff">if</span></span>(tracetag! = 0<span style="color: #000000"><span style="color: #000000">) {trace.tracebegin (tracetag, msg.target.getTraceName (msg)); } </span></span><span style="color: #0000ff"><span style="color: #0000ff">Try</span></span><span style="color: #000000"><span style="color: #000000">{msg.target.dispatchMessage (msg); } </span></span><span style="color: #0000ff"><span style="color: #0000ff">finally</span></span><span style="color: #000000"><span style="color: #000000"> { </span></span><span style="color: #0000ff"><span style="color: #0000ff">if</span></span>(tracetag! = 0<span style="color: #000000"><span style="color: #000000">) {trace.traceend (tracetag); } } </span></span><span style="color: #0000ff"><span style="color: #0000ff">if</span></span>(logging! =<span style="color: #0000ff"><span style="color: #0000ff">NULL</span></span><span style="color: #000000"><span style="color: #000000">) {logging.println (</span></span>"<<<<< finished to" + msg.target + "" +<span style="color: #000000"><span style="color: #000000">msg.callback); } </span></span><span style="color: #008000"><span style="color: #008000">//</span></span><span style="color: #008000">make <span style="color: #008000">sure that during the course of dispatching</span> the</span><span style="color: #008000"><span style="color: #008000">//</span></span><span style="color: #008000">The identity of the <span style="color: #008000">thread wasn ' t Corrupted.</span></span> <span style="color: #0000ff"><span style="color: #0000ff">Final</span></span> <span style="color: #0000ff"><span style="color: #0000ff">Long</span></span>Newident =<span style="color: #000000"><span style="color: #000000">binder.clearcallingidentity (); </span></span><span style="color: #0000ff"><span style="color: #0000ff">if</span></span>(ident! =<span style="color: #000000"><span style="color: #000000">Newident) {LOG.WTF (TAG,</span></span>"Thread identity changed from 0x" + long.tohexstring (ident) + "to 0x" + Lon G.tohexstring (newident) + "while dispatching to" + msg.target.getClass (). getName () + "" + Msg.callback + "what=" +<span style="color: #000000"><span style="color: #000000">msg.what); } msg.recycleunchecked (); } }</span></span></pre><p><p>The Mylooper method is called first in the loop method:</p></p><pre><pre> <span style="color: #008000">/**</span> <span style="color: #008000"> * Return The Looper object associated with the current Thread. Returns * NULL if the calling thread is not associated with a Looper. </span> <span style="color: #008000">*/</span> <span style="color: #0000ff"></span> public <span style="color: #0000ff">Static</span> <span style="color: #000000">@Nullable Looper mylooper () { </span><span style="color: #0000ff">return</span> <span style="color: #000000"> sthreadlocal.get (); }</span></pre></pre><p><p>The Mylooper method returns the Looper object associated with the current line threads. If the current thread does not have any Looper objects associated with it, the method returns Null.</p></p><p><p>To see the source of the loop method, you can know that when the thread does not have any Looper objects associated with it, The loop method throws a run-time exception, prompting that there is no looper in the current THREADS. To resolve this problem, you can create a Looper object by executing the Looper.prepare () method before the loop method is Called. Continue to look at the source of the loop method, you can see that the method is a dead loop, the only way to jump out of the loop is Queue.next () returns the object is Null. In the previous article, we analyzed that Queue.next () reads the message in messagequeue, and the next () method returns null, stating that there is no message in messagequeue, that is, the messgaequeue called the Quit Method. So when will MessageQueue call the Quit method? Take a look at Looper's quit Method:</p></p><pre><pre><span style="color: #0000ff"></span> public <span style="color: #0000ff">void</span> <span style="color: #000000">quit () { mqueue.quit (</span><span style="color: #0000ff">false</span><span style="color: #000000">);}</span></pre></pre><p><p>And the quitsafely method of Looper:</p></p><pre><pre><span style="color: #0000ff"></span> public <span style="color: #0000ff">void</span> <span style="color: #000000">quitsafely () { mqueue.quit (</span><span style="color: #0000ff">true</span><span style="color: #000000">);}</span></pre></pre><p><p>The Quit method and the Quitsafely method of Looper cause MessageQueue to call the quit method, so it is recommended to call the Looper's quit () method or the Quitsafely () method when Looper is not needed. To avoid an infinite loop of loop methods.</p></p><p><p>To know the difference between Looper's quit method and quitsafely method, Let's look at Messgaequeue's quit Method:</p></p><pre> <span style="color: #0000ff"><span style="color: #0000ff">void</span></span>Quit<span style="color: #0000ff"><span style="color: #0000ff">Boolean</span></span><span style="color: #000000"><span style="color: #000000">Safe) { </span></span><span style="color: #0000ff"><span style="color: #0000ff">if</span></span>(!<span style="color: #000000"><span style="color: #000000">Mquitallowed) { </span></span><span style="color: #0000ff"><span style="color: #0000ff">Throw</span></span> <span style="color: #0000ff"><span style="color: #0000ff">New</span></span>IllegalStateException ("Main thread not allowed to Quit.")<span style="color: #000000"><span style="color: #000000">); } </span></span><span style="color: #0000ff"><span style="color: #0000ff">synchronized</span></span>(<span style="color: #0000ff"><span style="color: #0000ff"></span> this</span><span style="color: #000000"><span style="color: #000000">) { </span></span><span style="color: #0000ff"><span style="color: #0000ff">if</span></span><span style="color: #000000"><span style="color: #000000">(mquitting) {</span></span><span style="color: #0000ff"><span style="color: #0000ff">return</span></span><span style="color: #000000"><span style="color: #000000">; } mquitting</span></span>=<span style="color: #0000ff"><span style="color: #0000ff">true</span></span><span style="color: #000000"><span style="color: #000000">; </span></span><span style="color: #0000ff"><span style="color: #0000ff">if</span></span><span style="color: #000000"><span style="color: #000000">(safe) {removeallfuturemessageslocked (); } </span></span><span style="color: #0000ff"><span style="color: #0000ff">Else</span></span><span style="color: #000000"><span style="color: #000000">{removeallmessageslocked (); } </span></span><span style="color: #008000"><span style="color: #008000">//</span></span><span style="color: #008000"><span style="color: #008000">We can assume mptr! = 0 because mquitting was previously false.</span></span><span style="color: #000000"><span style="color: #000000">Nativewake (mptr); } }</span></span></pre><p><p>Secure exit, The removeallfuturemessageslocked () method is called, which sets a flag that will not exit safely until all messages in the message queue have been processed, and quit calls removeallmessageslocked ( ), Exit Directly.</p></p><p><p>Let's look at the loop method below, focusing on this sentence:</p></p><pre><pre>Msg.target.dispatchMessage (msg);</pre></pre><p><p>In the overview of the Android message mechanism, we have said that target is a property of the message, and its type is handler,msg.target, which is the object that sent the Message. As a result, the message sent by handler is finally given to itself to invoke the DispatchMessage method, but the DispatchMessage method is called in the Looper loop method, So where is the Looper loop method executed? Executed in the same thread as when the handler was Created.</p></p><p><p>Activitythread (main Thread) will initialize looper when it is created, so we can use handler directly in the main thread, when we need to update the ui, we can send the message through handler, and finally we can go back to the main thread to update the UI.</p></p><p><p></p></p><p><p>In addition to this, Looper provides some other methods, such as the Preparemainlooper method:</p></p><pre> <span style="color: #008000"><span style="color: #008000">/**</span></span><span style="color: #008000"><span style="color: #008000">* Initialize The current thread as a looper, marking it as a * application ' s main looper. The main looper for your application * are created by the Android environment, so we should never need * to call T His function yourself. See Also: {</span></span><span style="color: #808080"><span style="color: #808080">@link</span></span><span style="color: #008000"><span style="color: #008000">#prepare ()}</span></span><span style="color: #008000"><span style="color: #008000">*/</span></span> <span style="color: #0000ff"><span style="color: #0000ff"></span> public</span> <span style="color: #0000ff"><span style="color: #0000ff">Static</span></span> <span style="color: #0000ff"><span style="color: #0000ff">void</span></span><span style="color: #000000"><span style="color: #000000">preparemainlooper () {prepare (</span></span><span style="color: #0000ff"><span style="color: #0000ff">false</span></span><span style="color: #000000"><span style="color: #000000">); </span></span><span style="color: #0000ff"><span style="color: #0000ff">synchronized</span></span>(Looper.<span style="color: #0000ff"><span style="color: #0000ff">class</span></span><span style="color: #000000"><span style="color: #000000">) { </span></span><span style="color: #0000ff"><span style="color: #0000ff">if</span></span>(smainlooper! =<span style="color: #0000ff"><span style="color: #0000ff">NULL</span></span><span style="color: #000000"><span style="color: #000000">) { </span></span><span style="color: #0000ff"><span style="color: #0000ff">Throw</span></span> <span style="color: #0000ff"><span style="color: #0000ff">New</span></span>IllegalStateException ("the main Looper has already been prepared."<span style="color: #000000"><span style="color: #000000">); } smainlooper</span></span>=<span style="color: #000000"><span style="color: #000000">Mylooper (); } }</span></span></pre><p><p>This method instantiates the current thread as a looper, but is the looper of the main thread. The Android system will create the main thread of the Looper for us, and we do not need to manually call the Method. The essence of the method is also realized by prepare Method.</p></p><p><p>Again like the Getmainlooper method:</p></p><pre><pre> <span style="color: #008000">/**</span> <span style="color: #008000"> * Returns The application ' s main looper, which lives in the main thread of the Application. </span> <span style="color: #008000">*/</span> <span style="color: #0000ff"></span> public <span style="color: #0000ff">Static</span> <span style="color: #000000">Looper getmainlooper () { </span><span style="color: #0000ff">synchronized</span> (Looper. <span style="color: #0000ff"> Class</span><span style="color: #000000">) { </span><span style="color: #0000ff">return</span> <span style="color: #000000"> smainlooper; } }</span></pre></pre><p><p>This method allows us to get the looper of the main thread from Anywhere.</p></p><p><p></p></p><p><p>"original" Source Angle Analysis Android message mechanism series (V) How--looper works</p></p></span>

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.