神刀安全网

Android Handler消息机制

简单应用场景

  • 在子线程向主线程发送消息,一般刷新主线程的UI
  • 主线程向子线程发送消息, 一般为启动异步阻塞任务
class MessageMechanismActivity : AppCompatActivity() {     companion object {         private const val TAG = "MessageMechanism"         private const val MSG_UPDATE_START = 1         private const val MSG_UPDATE_OVER = 2     }     private var mainHandler: Handler? = null     private var threadHandler: Handler? = null      override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         setContentView(R.layout.activity_message_mechanism)          // thread1 -> main thread         mainHandler = TestHandler() // main thread中         this.btn_handler_in_main.setOnClickListener{             mainHandler!!.sendEmptyMessage(MSG_UPDATE_START)             // thread1             object : Thread() {                 override fun run() {                     Thread.sleep(2000)                     // thread1->threadMain                     mainHandler!!.sendEmptyMessage(MSG_UPDATE_OVER)                 }             }.start()         }                  // main thread -> thread2         // thread2         object : Thread() {             override fun run() {                 Looper.prepare()                 threadHandler = TestHandler() // 在此线程中创建Handler                 Looper.loop()// may block             }         }.start()                  this.btn_handler_in_other_thread.setOnClickListener {             // threadMain -> thread2             threadHandler!!.sendEmptyMessage(MSG_UPDATE_START)         }     }       class TestHandler : Handler() {         init {             Log.d(TAG, "init:${Thread.currentThread().name}")         }         override fun handleMessage(msg: Message?) {             Log.d(TAG, "thread:${Thread.currentThread().name}")             super.handleMessage(msg)             when(msg?.what){                 MSG_UPDATE_START -> {                     val sdf = SimpleDateFormat("HH:mm:ss", Locale.CHINA)                     Log.d(TAG, "开始更新:${sdf.format(Date())}")                 }                 MSG_UPDATE_OVER -> {                     val sdf = SimpleDateFormat("HH:mm:ss", Locale.CHINA)                     Log.d(TAG, "完成更新:${sdf.format(Date())}")                 }             }         }     } } 

类说明

Thread

  • 成员 ThreadLocal.ThreadLocalMap。用于存储各种ThreadLocal数据

ThreadLocal

  • 一个对象能在多个线程中保存各自的数据,保存或获取数据时会调用当前线程的ThreadLocal.ThreadLocalMap进行处理

Looper

  • 成员MessageQueue
  • 成员Thread。创建Looper的当前线程
  • 成员ThreadLocal< Looper >, 用于在当前线程存储当前Looper

MessageQueue

Handler

  • 成员Looper。当前线程的Looper
  • 成员MessageQueue。Looper中的MessageQueue

Handler发送消息流程

  • 在线程A中,创建Looper、MessageQueue、Handler,并用Looper维护MessageQueue
  • 在线程B中,调用Handler发送消息,添加消息到MessageQueue;
  • 在线程A中,Looper从MessageQueue拿出消息交给Handler处理
Android Handler消息机制

image.png

线程A中,创建Looper和MessageQueue
->Looper.prepare()。创建Looper和MessageQueue,并在当前线程的ThreadLocalMap中保存Looper

private static void prepare(boolean quitAllowed) {     // 一个线程只能创建一个Looper     if (sThreadLocal.get() != null) {         throw new RuntimeException("Only one Looper may be created per thread");     }     // 创建Looper并保存在当前线程的ThreadLocalMap中     sThreadLocal.set(new Looper(quitAllowed)); }  private Looper(boolean quitAllowed) {     mQueue = new MessageQueue(quitAllowed);     mThread = Thread.currentThread(); } 

线程A中,创建Handler
->Handler()

// Handler.class public public Handler(Callback callback, boolean async) {     // ...     // 获取当前线程的Looper     mLooper = Looper.myLooper();     // 当前线程中没有Looper则不能创建     if (mLooper == null) {         throw new RuntimeException(         "Can't create handler inside thread that has not called Looper.prepare()");     }     mQueue = mLooper.mQueue;     // ... }  // Looper.class public static @Nullable Looper myLooper() {     return sThreadLocal.get(); }  // ThreadLocal.class // 从当前线程中的ThreadLocalMap中获取ThreadLocal值 public T get() {     Thread t = Thread.currentThread();     ThreadLocalMap map = getMap(t);     if (map != null) {         ThreadLocalMap.Entry e = map.getEntry(this);         if (e != null) {             @SuppressWarnings("unchecked")             T result = (T)e.value;             return result;         }     }     return setInitialValue(); } 

线程A中,Looper维护MessageQueue
-> Looper.loop()

// Looper.loop核心代码 public static void loop() {     final Looper me = myLooper();     final MessageQueue queue = me.mQueue;     for (;;) {         // might block.因为queue.next()也是一个永真循环         Message msg = queue.next();          // msg.target是Handler,一般最终会调用Handler.handleMessage         msg.target.dispatchMessage(msg);     } }  //MessageQueue.class 轮询取出消息 Message next() {     for (;;) {         if (now < msg.when) {             // Next message is not ready.  Set a timeout to wake up when it is ready.             nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);         } else {             // Got a message.             mBlocked = false;             if (prevMsg != null) {                 prevMsg.next = msg.next;             } else {                 mMessages = msg.next;             }             msg.next = null;             if (DEBUG) Log.v(TAG, "Returning message: " + msg);             msg.markInUse();             return msg;         }     } } 

B线程中,发送消息
->Handler.sendMessage()->…->Handler.enqueueMessage()// 会设置msg.target = this
->MessageQueue.enqueueMessage()// 添加消息到消息队列

// MessageQueue.class 添加消息到消息队列相关代码 boolean enqueueMessage(Message msg, long when{     msg.when = when;     Message p = mMessages;     boolean needWake;     if (p == null || when == 0 || when < p.when) {         // 插到头部         msg.next = p;         mMessages = msg;         needWake = mBlocked;     } else {         // 插入到队列中间         Message prev;         for (;;) {             p = p.next;             if (p == null || when < p.when) {                 // 插入规则:或者是最后一个,或者根据处理事件顺利插入                 break;             }             if (needWake && p.isAsynchronous()) {                 needWake = false;             }          }          msg.next = p; // invariant: p == prev.next          prev.next = msg;     } } 

A线程中,拿出消息并处理
->Looper.loop()->Handler.dispatchMessage()
->message.callback.run() || mCallback.handleMessage(msg) || handleMessage(msg);

// Handler.class public void dispatchMessage(Message msg) {     if (msg.callback != null) {         handleCallback(msg);     } else {         if (mCallback != null) {             if (mCallback.handleMessage(msg)) {                 return;             }         }         handleMessage(msg);     } } 

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Android Handler消息机制

分享到:更多 ()