一、子線程向子線程通信
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 ( ) {
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 ;
}
.. ..
}
}