Handler進行線程通信以及對其源碼解析

一、子線程向子線程通信

package com.study.yang.handlercodedemo

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.Log
import android.view.View
import kotlinx.android.synthetic.main.activity_child_to_child.*

/**
 * 子線程向子線程發送消息
 */
class ChildToChildActivity : AppCompatActivity() {

    var handler: Handler? = null
    var content: String = ""

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_child_to_child)

        object : Thread() {
            override fun run() {
                super.run()
                Looper.prepare()
                handler = object : Handler() {
                    override fun handleMessage(msg: Message?) {
                        super.handleMessage(msg)
                        msg?.apply {
                            if (obj is String) {
                                Log.e("thread::", "111message::$this")
                                content = obj as String
                                runOnUiThread {
                                    tv_thread1.text = content
                                }
                            }
                        }
                    }
                }
                Looper.loop()
            }
        }.start()

    }

    fun sendMsg(view: View) {
        object : Thread() {
            override fun run() {
                super.run()
                handler?.apply {
                    val message = obtainMessage()
                    message?.obj = "子線程2"
                    sendMessage(message)
                }
            }
        }.start()
    }
}

二、子線程向主線程通信

package com.study.yang.handlercodedemo

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Message
import kotlinx.android.synthetic.main.activity_child_to_main.*

/**
 * 子線程向主線程發送消息
 */
class ChildToMainActivity : AppCompatActivity() {

    /**
     * 此處創建的Handler,默認就是在主線程中。
     * ActivityThread中的main方法
     * public static void main(String[] args) {
     *   ...
     *   Looper.prepareMainLooper();
     *  ...
     *  Looper.loop();
     *  }
     */
    var handler = object : Handler() {
        override fun handleMessage(msg: Message?) {
            super.handleMessage(msg)
            msg?.apply {
                val text = obj as String
                tv.text = text
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_child_to_main)
        object : Thread() {
            override fun run() {
                super.run()
                val message = Message.obtain()
                message.obj = "品蘭"
                handler.sendMessage(message)
            }
        }.start()
    }
}

三、主線程向子線程通信

package com.study.yang.handlercodedemo

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.Log
import android.view.View

/**
 * 主線程向子線程發送消息
 */
class MainToChildActivity : AppCompatActivity() {

    var handler: Handler? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main_to_child)

        object : Thread() {
            override fun run() {
                super.run()
                Looper.prepare()
                handler = object : Handler() {
                    override fun handleMessage(msg: Message?) {
                        super.handleMessage(msg)
                        msg?.apply {
                            if (obj is String) {
                                Log.e("thread::", "111message::$this")
                            }
                        }
                    }
                }
                Looper.loop()
            }
        }.start()

    }

    fun sendMsg(view: View){
        handler?.apply {
            val message = obtainMessage()
            message.obj="我在主線程向子線程發送消息"
            sendMessage(message)
        }
    }
}

四、Handler源碼解析

4.1 爲什在主線程中創建Handler的時候不用調用Looper.prepare()和Looper.loop()

此處創建的Handler,默認就是在主線程中。
ActivityThread中的main方法
public static void main(String[] args) {
...
Looper.prepareMainLooper();
...
Looper.loop();
}

4.2 子線程中創建Handler注意事項

子線程中創建Handler,這段示例代碼可以在Looper源碼中找到
class LooperThread extends Thread {
	public Handler mHandler;
       public void run() {
            Looper.prepare();
 
           mHandler = new Handler() {
               public void handleMessage(Message msg) {
                   // process incoming messages here
               }
            };
  
            Looper.loop();
        }
  }

4.3 Handler是如何做到線程隔離的

利用ThreadLocal實現線程隔離,ThreadLocal內部維護了一個ThreadLocalMap對象。它的存儲數據結構是
以Key-Value的形式進行的,其中Key就是當前ThreadLocal的對象,Value是Looper對象。

4.4 Handler源碼

創建Handler的過程中走的流程如下,調用Looper類中的Looper.prepare()方法
 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");
     }
    //將創建的Looper保存到ThreadLocal中
    sThreadLocal.set(new Looper(quitAllowed));
 }

 //Looper類中創建Looper的同時創建該Handler的消息隊列
 private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
 }

 調用Handler類中的構造方法創建Handler,具體如下:
   public Handler(Callback callback, boolean async) {
       ...
       //從ThreadLocal中取出之前保存的Looper
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        //該Looper中的消息隊列
        mQueue = mLooper.mQueue;
      ....
    }


 //調用Handler類中的sendMessage方法發送消息,最終調用
  enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)進行消息隊列的排序。

 //調用MessageQueue類的enqueueMessage方法進行消息排列
  按照消息執行時間進行排序,此處用的是優先隊列算法
   if (p == null || when == 0 || when < p.when) {
        // New head, wake up the event queue if blocked.
        	msg.next = p;
        	mMessages = msg;
        	needWake = mBlocked;
   } else {
            needWake = mBlocked && p.target == null && msg.isAsynchronous();
            Message prev;
            for (;;) {
                prev = p;
                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;
    }
    
最後調用Looper.loop()開啓消息隊列輪詢,具體方法如下:
 public static void loop() {
 		//找到當前線程的Looper
        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;
        ....
        for (;;) {
        	//開始輪詢消息
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            ....
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章