Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use the Android message mechanism Handler

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "how to use Android message mechanism Handler". In daily operation, I believe many people have doubts about how to use Android message mechanism Handler. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts about "how to use Android message mechanism Handler". Next, please follow the editor to study!

Overview

Handler is the upper interface of Android message mechanism. It makes it easy to switch a task to the same thread as Handler to execute. Typically, the usage scenario for Handler is to update UI.

The use of Handler

In the child thread, a time-consuming operation is performed, and after the operation is completed, a message is sent informing the main thread to update the UI.

Public class Activity extends android.app.Activity {private Handler mHandler = new Handler () {@ Override public void handleMessage (Message msg) {super.handleMessage (msg); / / Update UI}} @ Override public void onCreate (Bundle savedInstanceState, PersistableBundle persistentState) {super.onCreate (savedInstanceState, persistentState); setContentView (R.layout.activity_main) New Thread (new Runnable () {@ Override public void run () {/ / execute a time-consuming task. / / after the task has been executed Notify Handler to update UI Message message = Message.obtain () Message.what = 1; mHandler.sendMessage (message);}}) .start ();}} Handler architecture

Handler message mechanism mainly includes: MessageQueue, Handler, Looper these three parts, and Message.

Message: messages that need to be delivered, and data can be passed

MessageQueue: message queue, but its internal implementation is not a queue to use, but to maintain the message list through the data structure of a single linked list, which has the advantage of inserting and deleting. The main function is to deliver messages to the message pool (MessageQueue.enqueueMessage) and to take messages from the message pool (MessageQueue.next).

Handler: message helper class, the main function is to send various message events to the message pool (Handler.sendMessage) and handle the corresponding message events (Handler.handleMessage)

Looper: message controller, continuous cyclic execution (Looper.loop), reads messages from MessageQueue, and distributes messages to target processors according to the distribution mechanism.

As can be seen from the class diagram above:

Looper has a MessageQueue message queue

MessageQueue has a set of Message to be processed

Record the Handler that sends and processes messages in Message

There are Looper and MessageQueue in Handler.

The relationship among MessageQueue, Handler, and Looper: there can be only one Looper,Looper in each thread that is stored in ThreadLocal. The main thread (the UI thread) has already created a Looper, so you no longer need to create a Looper in the main thread, but you need to create a Looper in other threads. There can be multiple Handler in each thread, that is, a single Looper can process messages from multiple Handler. A MessageQueue is maintained in Looper to maintain the message queue, and the Message in the message queue can come from different Handler.

The running process of Handler

When the child thread completes the time-consuming operation, when the Handler sends a message, MessageQueue.enqueueMessage is called to add the message to the message queue. When the loop is started through Looper.loop, the message is constantly read from the message pool, that is, the MessageQueue.next is called, then the dispatchMessage method of the target Handler (that is, the Handler that sent the message) is called to deliver the message, and then returned to the thread where the Handler resides. The target Handler receives the message, calls the handleMessage method, receives the message, and processes the message.

Source code analysis creates Handlerclass LooperThread extends Thread {public Handler mHandler; public void run () {Looper.prepare () in the child thread MHandler = new Handler () {public void handleMessage (Message msg) {/ / process incoming messages here}; Looper.loop ();}}

As you can see from the above, the Looper.prepare () method is called before the Handler is created in the child thread, and the Looper.loop () method is also called after the Handler is created. Earlier, we didn't need these two steps to create Handler in the main thread, because the system did it for us.

Looper of the main thread

In the main method of ActivityThread, Looper.prepareMainLooper () is called to initialize the Looper, and the Looper.loop () method is called to open the loop.

Public final class ActivityThread extends ClientTransactionHandler {/ /... Public static void main (String [] args) {/ /... Looper.prepareMainLooper () / /... Looper.loop ();}} Looper

As you can see from above, to use Handler, you must first create a Looper.

Initialize Looper:

Public final class Looper {public static void prepare () {prepare (true);} private static void prepare (Boolean quitAllowed) {if (sThreadLocal.get ()! = null) {throw new RuntimeException ("Only one Looper may be created per thread");} sThreadLocal.set (new Looper (quitAllowed)) } public static void prepareMainLooper () {prepare (false); synchronized (Looper.class) {if (sMainLooper! = null) {throw new IllegalStateException ("The main Looper has already been prepared.");} sMainLooper = myLooper () }} private Looper (Boolean quitAllowed) {mQueue = new MessageQueue (quitAllowed); mThread = Thread.currentThread ();} / /.}

As you can see from above, Looper cannot be created repeatedly, only one can be created per thread. Create a Looper and save it in ThreadLocal. ThreadLocal is the thread local storage area (ThreadLocal Storage, referred to as TLS), each thread has its own private local storage area, different threads can not access each other's TLS area.

Turn on Looper

Public final class Looper {/ /... Public static void loop () {/ / gets the Looper object stored by TLS final Looper me = myLooper (); if (me = = null) {throw new RuntimeException ("No Looper; Looper.prepare () wasn't called on this thread.");} final MessageQueue queue = me.mQueue / / enter the loop main loop method for (;;) {Message msg = queue.next () / / it may block because the next () method may wirelessly loop if (msg = = null) {/ / No message indicates that the message queue is quitting. Return;} / / This must be ina local variable, in case a UI event sets the logger final Printer logging = me.mLogging If (logging! = null) {logging.println ("> Dispatching to" + msg.target + "" + msg.callback + ":" + msg.what) } / /... Final long dispatchStart = needStartTime? SystemClock.uptimeMillis (): 0; final long dispatchEnd; try {/ / get the target Handler of msg, and then distribute Message msg.target.dispatchMessage (msg); dispatchEnd = needEndTime? SystemClock.uptimeMillis (): 0;} finally {if (traceTag! = 0) {Trace.traceEnd (traceTag) }} / /... Msg.recycleUnchecked ();} Handler

Create a Handler:

Public class Handler {/ /... Public Handler () {this (null, false);} public Handler (Callback callback, Boolean async) {/ /... / must execute Looper.prepare () before getting the Looper object, otherwise null mLooper = Looper.myLooper () If (mLooper = = null) {throw new RuntimeException ("Can't create handler inside thread" + Thread.currentThread () + "that has not called Looper.prepare ()") } mQueue = mLooper.mQueue; / / message queue, from the Looper object mCallback = callback; / / callback method mAsynchronous = async; / / sets whether the message is handled asynchronously}}

Send a message:

Child threads send messages through either the post () method of Handler or the send () method, which ends up calling the sendMessageAtTime () method.

Post method:

Public final Boolean post (Runnable r) {return sendMessageDelayed (getPostMessage (r), 0);} public final Boolean postAtTime (Runnable r, long uptimeMillis) {return sendMessageAtTime (getPostMessage (r), uptimeMillis);} public final Boolean postAtTime (Runnable r, Object token, long uptimeMillis) {return sendMessageAtTime (getPostMessage (r, token), uptimeMillis);} public final Boolean postDelayed (Runnable r, long delayMillis) {return sendMessageDelayed (getPostMessage (r), delayMillis) } private static Message getPostMessage (Runnable r) {Message m = Message.obtain (); m.callback = r; return m;}

Send method:

Public final Boolean sendMessage (Message msg) {return sendMessageDelayed (msg, 0);} public final Boolean sendEmptyMessage (int what) {return sendEmptyMessageDelayed (what, 0);} public final Boolean sendEmptyMessageDelayed (int what, long delayMillis) {Message msg = Message.obtain (); msg.what = what; return sendMessageDelayed (msg, delayMillis);} public final Boolean sendEmptyMessageAtTime (int what, long uptimeMillis) {Message msg = Message.obtain (); msg.what = what Return sendMessageAtTime (msg, uptimeMillis);} public final Boolean sendMessageDelayed (Message msg, long delayMillis) {if (delayMillis < 0) {delayMillis = 0;} return sendMessageAtTime (msg, SystemClock.uptimeMillis () + delayMillis);} sendMessageAtTime () 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) } private Boolean enqueueMessage (MessageQueue queue, Message msg, long uptimeMillis) {msg.target = this; if (mAsynchronous) {msg.setAsynchronous (true);} return queue.enqueueMessage (msg, uptimeMillis);} distribute messages

In the loop () method, after getting the next message, execute msg.target.dispatchMessage (msg) to distribute the message to the target Handler.

Public class Handler {/ /... Public void dispatchMessage (Message msg) {if (msg.callback! = null) {/ / when the callback method exists in Message, call the callback method handleCallback (msg) } else {if (mCallback! = null) {/ / when the Callback member variable exists in Handler, call back its handleMessage () method if (mCallback.handleMessage (msg)) {return }} / / Handler's own callback method handleMessage (msg);}} private static void handleCallback (Message message) {message.callback.run () }} at this point, the study on "how to use the Android messaging mechanism Handler" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report