Looper 类 模拟了loop方法,quit 方法用于退出模拟的死循环
package com.yuixu.test2
import android.util.Log
class MyLooper {
var mThread:Thread
companion object{
var threadLocal =ThreadLocal<MyLooper>()
fun myLooper():MyLooper{
return threadLocal.get()
}
fun loop(){
Log.e("loop","${myLooper().messageQueue.inWait}")
Log.e("loop","${myLooper().messageQueue.toString()}")
myLooper().waitMessage()
}
fun quit(handler: MyHandler){
Log.e("quit",handler.mLooper.mThread.name)
Log.e("quit","${handler.mQueue.toString()}")
handler.mQueue.inWait=false
handler.mQueue.quitAll()
Log.e("quit","${handler.mLooper.messageQueue.inWait}")
}
}
fun waitMessage(){
messageQueue.next()
}
var messageQueue: MyMessageQueue
constructor(){
Log.e("threadLooper",Thread.currentThread().name)
threadLocal.set(this)
mThread= Thread.currentThread()
messageQueue=MyMessageQueue(true)
}
}
MessageQueue 模拟了 enqueueMessage。但由于模拟程序是在next 中写一个死循环,
所以省掉了休眠和唤醒的流程 (API 中的逻辑是分别调用 native中的nativePollOnce使Looper关联线程休眠。和 nativeWake 方法唤醒休眠的线程)
package com.yuixu.test2
import android.util.Log
class MyMessageQueue(isAllowQuit: Boolean) {
var isAllowQuit:Boolean=isAllowQuit
var inWait:Boolean=true
private var mMessage: MyMessage?=null
fun enqueueMessage(message: MyMessage){
var isNeedWake=false
if(mMessage==null){
isNeedWake=true
mMessage=message
}else {
message.mHandler?.let {
var temp: MyMessage = mMessage!!
while (true) {
if (temp.next == null){
temp.next=message
break
}else{
temp = temp.next!!
}
}
}
}
//由于模拟程序是循环取出。就不需要唤醒了。正常的handler 应该是需要唤醒loop方法中休眠的线程
if(isNeedWake){
}
}
fun quitAll(){
if(isAllowQuit){
while(true){
var temp:MyMessage?=mMessage
if(temp!=null){
mMessage=temp.next
temp=null
}else{
break
}
}
mMessage=null
}
}
/**
* 模拟等待消息
*/
fun next(){
while (true){
Thread.sleep(1000)
mMessage?.mHandler?.let {
handler->
handler.callBack?.let {
callback->
mMessage?.let {
message->
Log.e("targetMessage",Thread.currentThread().name)
callback(message)
mMessage=message.next
}
}
}
if(!inWait){
break
}
}
}
fun wake(){
mMessage?.mHandler?.let {
handler->
handler.callBack?.let {
callback->
mMessage?.let {
message->
Log.e("targetMessage",Thread.currentThread().name)
}
}
}
}
}
用kotlin中的线程休眠和唤醒优化上面的类
package com.yuixu.test2
import android.util.Log
import java.lang.Exception
import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.Condition
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
class MyMessageQueue(isAllowQuit: Boolean) {
var isAllowQuit:Boolean=isAllowQuit
var inWait:Boolean=true
private var mMessage: MyMessage?=null
fun enqueueMessage(message: MyMessage){
var isNeedWake=false
if(mMessage==null){
isNeedWake=true
mMessage=message
}else {
message.mHandler?.let {
var temp: MyMessage = mMessage!!
while (true) {
if (temp.next == null){
temp.next=message
break
}else{
temp = temp.next!!
}
}
}
}
//由于模拟程序是循环取出。就不需要唤醒了。正常的handler 应该是需要唤醒loop方法中休眠的线程
if(isNeedWake){
wake()
}
}
fun quitAll(){
if(isAllowQuit){
while(true){
var temp:MyMessage?=mMessage
if(temp!=null){
mMessage=temp.next
temp=null
}else{
break
}
}
mMessage=null
}
}
/**
* 模拟等待消息
*/
private var condition: Condition?=null
val lock=ReentrantLock()
fun next(){
condition =lock.newCondition()
while (true) {
if (mMessage == null) {
// Log.e("aa", "阻塞${condition.toString()}")
lock.withLock {
//
Log.e("aa", "阻塞${condition.toString()}")
condition?.await(1,TimeUnit.DAYS)
Log.e("aa", "唤醒${condition.toString()}")
}
}
mMessage?.mHandler?.let { handler ->
handler.callBack?.let { callback ->
mMessage?.let { message ->
Log.e("targetMessage", Thread.currentThread().name)
callback(message)
mMessage = message.next
}
}
}
if (!inWait) {
break
}
}
}
fun wake(){
try {
lock.lock()
Log.e("aa", "唤醒${condition.toString()}")
condition?.signal()
lock.unlock()
}catch (e:Exception){
Log.e("error","${e.message}")
}
}
}
后面几个类就比较简单了
class MyHandler (looper: MyLooper,callback: ((MyMessage) -> Unit)?){
var mLooper:MyLooper
var mQueue:MyMessageQueue
var callBack: ((MyMessage) -> Unit)? =callback
init {
mLooper=looper
mQueue=looper.messageQueue
}
fun sendMessage(message: MyMessage){
message.mHandler=this
mQueue.enqueueMessage(message)
}
}
class MyMessage {
var what:Int=-1
var next:MyMessage?=null
var mHandler: MyHandler?=null
var workSourceUid:String?=null
}
调用的demo 。由于不能在主线程创建死循环。所以另启一个线程当中接收消息的线程。
这里由于我的Looper的构造方法没有私有化。所以MyLooper()就相当于Looper.prepare()
两个按钮一个调用退出当前的死循环。一个调用发送十条消息
class MainModel(binding: ActivityMainBinding, context: Activity) :
MyBaseModel<ActivityMainBinding>(binding, context) {
var thread:Thread
var handler:MyHandler?=null
init {
bindListener(binding.tvHello,binding.tvHello2)
thread= Thread(Runnable {
MyLooper()
MyLooper.myLooper()?.let {
Log.e("target_thread", Thread.currentThread().name)
handler = MyHandler(it, {
Log.e("target_thread", Thread.currentThread().name+" what:${it.what}")
Thread.sleep(1000)
})
}
MyLooper.loop()
})
thread.start()
}
override fun onDestroy() {
handler?.let {
MyLooper.quit(it)
}
}
override fun onClick(v: View?) {
v?.let {
when(v.id){
R.id.tv_hello->{
Thread(Runnable {
for(i in 1..10){
var msg=MyMessage()
msg.what=i
Log.e("send_thread", Thread.currentThread().name+"${msg.what}")
handler?.sendMessage(msg)
}
}).start()
}
R.id.tv_hello2->{
handler?.let {
MyLooper.quit(it)
}
}
else->{}
}
}
}
}