Android Update UI Four ways to explain _android

Source: Internet
Author: User
Tags current time message queue prepare

Objective

It is believed that every Android developer knows that the update UI can only be done in the main thread, and that if you need to update the UI after the child thread executes the task, you need to use handler to jump to the main thread. Here are several ways to manipulate the UI.

First, the use of Handler handlemessage ()

Construction of Handler

Public Handler () {This
(null, FALSE);
}

Public Handler (Callback Callback, Boolean async) {
 if (find_potential_leaks) { 
   final class<? extends handler& Gt Klass= getclass (); 
   if (Klass.isanonymousclass () | | Klass.ismemberclass () | | Klass.islocalclass ()) && 
       (Klass.getmodifiers () &modifier.static) = = 0) { 
     log.w (TAG, "the Followinghandler class should be static or leaks might occur: "+ 
       klass.getcanonicalname ()); 
   } 
 Mlooper = Looper.mylooper (); 
 if (Mlooper = = null) { 
   throw new RuntimeException ( 
     "Can" T create handler Insidethread that has not called looper . Prepare () "); 
 } 
 Mqueue = Mlooper.mqueue; 
 Mcallback = null; 
}

The visible construct handler needs looper, and no words throw an exception.Looper.myLooper()

will return a Looper object, how to return it, look at the source code

public static Finallooper Mylooper () {return 
 (Looper) sthreadlocal.get (); 
}

Obviously, the myLooper() Looper object was removed from the threadlocal. So the question is, when are we going to deposit Looper objects into threadlocal? In fact, the mystery lies in Looper.prepare() the time we call, look at the source code

public static final void prepare () { 
  if (sthreadlocal.get ()!= null) { 
    throw new runtimeexception (' Only one looper May is created per thread "); 
  } 
  Sthreadlocal.set (New Looper ()); 
}

It is visible that a new Looper object is created when the Looper object that sthreadlocal takes out is empty.

This shows that you need to call before instantiating a hanlder, Looper.prepare() or you will throw an exception unless you are building handler in the main thread. The system has built a looper for the main thread at the time it was created.

Creation of message

The most common practice in general is

Message message = new Message ();  
Mhandler.sendmessage (message);

But to do so each time need a new message, more waste of space, we can use to obtainMessage(); look at the source code

Public final message Obtainmessage (int what, int arg1, int. arg2, Object obj) {return 
  Message.obtain (this, what, arg1,a RG2, obj); 
}

This method returns Message.obtain(this, what, arg1,arg2, obj) , which means obtainMessage() that it is the same as the function, so it can be used directly Message.obtain(this, what, arg1,arg2, obj) .

Again look at obtain() the source code

public static message Obtain (Handler h, int what, int. arg1, int arg2, Object obj) {message 
   M = obtain (); 
   M.target = h; 
   M.what = what; 
   M.ARG1 = arg1; 
   M.ARG2 = arg2; 
   M.obj = obj; 
   return m; 
}

Look at the code above, we still have to find obtain's parameterless structure.

public static message obtain () { 
   synchronized (spoolsync) { 
     if (sPool!= null) {message 
       m = sPool; 
       SPool = M.next; 
       M.next = null; 
       m.flags = 0; Clear In-useflag 
       spoolsize--; 
       return m; 
     } 
   } 
   return new Message (); 
 }

It's not hard to see that obtain returns a Message object from the pool of messages, and if the message pool is empty and then creates a new message, it's obtain() reasonable to get a message for general use.

parameter of message

public int Arg1
public int Arg2

If you only need to store integer data, use Arg1 and arg2

Public Object obj

Any object that is sent to the receiver. When you use a message object to pass messages between threads, if it contains a parcelable struct class (not a class implemented by the application), this field must be Non-null (non-null).

public int What

User-defined message code so that the recipient can learn about the message. Each handler contains its own message code, so there is no need to worry about custom messages that conflict with other handlers.

If you need to pass the bundle object, use thesetData(Bundle)

Public Handler Target

The handler object that receives this message.

Several ways to handle messages

Public Final Boolean SendMessage (Message msg) {return sendmessagedelayed (msg, 0);//Direct call to Sendmessagedelayed (), just no time delay}
  Public Final Boolean sendmessagedelayed (Message msg, long Delaymillis) {if (Delaymillis < 0) {Delaymillis = 0;
Return Sendmessageattime (MSG, systemclock.uptimemillis () + delaymillis);//Call Sendmessageattime, current time plus delay time.  
 public boolean sendmessageattime (Message msg, long Uptimemillis) {MessageQueue queue = Mqueue;     
  if (queue = = null) {runtimeexception e = new RuntimeException (this + "sendmessageattime () called with no Mqueue");    
  LOG.W ("Looper", E.getmessage (), E);  
 return false; return Enqueuemessage (Queue, MSG, uptimemillis);//Call Enqueuemessage, enclose message queue and time} private Boolean enqueuemessage (Messag  
 Equeue queue, Message msg, long uptimemillis} {msg.target = this;  
 if (masynchronous) {msg.setasynchronous (true);
Return Queue.enqueuemessage (msg, uptimemillis);//The Last Call queue's Insert message method, only the time of insertion is made. }

Through the analysis above, no matter which method the handler calls, the sendMessage() end is to insert the message into the queue, there is no other action. queue.enqueueMessage(msg, uptimeMillisin this way we also know that the order in which looper processes messages is polling based on how quickly the message is inserted.

How to add empty messages

Public final Boolean sendemptymessage (int what) {return
  sendemptymessagedelayed (what, 0);
}
Public final Boolean sendemptymessagedelayed (int what, long Delaymillis) { 
msg = Message.obtain (); 
Msg.what = what; 
Return sendmessagedelayed (msg, delaymillis); 

Second, Handler post () method

Use steps

Handler.post (New Runnable () { 
      @Override public 
      Void Run () 
        is available for UI operations.
      } 
    });

Look at the Post method of the source code

Public Final Boolean post (Runnable R) {return 
  sendmessagedelayed (Getpostmessage (R), 0); 
}

See here is not an epiphany, the original post method is actually sent a message.

Again look at getPostMessage(r) the source code

Private Final Message Getpostmessage (Runnable r) {message
  m = Message.obtain ();
  M.callback = R;
  return m;
}

This is clear, this method encapsulates the Runnable object as a message, and then sendmessagedelayed sends the past to handler processing.

Here we have to know how the message was taken out, the current MessageQueue exist Mmessages (that is, the message to be processed), and then take the message out, and then let the next message become mmessages, otherwise enter a blocking state, until there is a new message to the team. Whenever a message is taken out, it is passed to the Msg.target dispatchMessage() , which msg.target is the statement in the handler Enqueuemessage method msg.target = this , the current handler object. So the next point is naturally back todispatchMessage()

public void DispatchMessage (message msg) { 
  if (msg.callback!= null) { 
    handlecallback (msg); 
  } else { 
    if ( Mcallback!= null) { 
      if (Mcallback.handlemessage (msg)) {return 
        ; 
      } 
    } 
    Handlemessage (msg); 
  } 

If a method is called, the Handler.post() callback != null method is executed handleCallback(msg);

Private final void Handlecallback (Message message) {
  message.callback.run ();
}

That is, the final Runnable object is handle processed. According to the handler principle, handler needs to instantiate the main thread post method before updating the UI.

The Post method of view

Look at the source code

public Boolean post (Runnable action) {
  Handler Handler;
  if (mattachinfo!= null) {
    handler = Mattachinfo.mhandler;
  } else {
    viewroot.getrunqueue (). Post (action);
    return true;
  }
  Return Handler.post (action);
}

At a glance, calling the Handlerd post method is essentially the same.

Iv. the Runonuithread () method in activity

Public final void Runonuithread (Runnable action) { 
  if (Thread.CurrentThread ()!= muithread) { 
    mhandler.post ( action); 
  } else { 
    action.run (); 
  } 
}

This method must have nothing to say, if the UI thread, direct run, not the words with the help ofhandler.post()
One thing to note is that this method only works in the activity.

Summarize

The above is the entire content of this article, I hope to be able to learn or work can bring some help, if you have questions you can message exchange.

Related Article

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.