自定义Looper线程中Looper.myLooper与主线程Looper等同的原因及疑问
Android Looper与Handler消息处理疑问解答
场景说明
我正在学习使用Looper和Handler进行消息处理。在主Activity中,点击Start按钮时,创建消息并尝试发送给自定义MyLooperThread的Looper对象。
代码实现
主Activity代码
package com.example.asynctaskdemo import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.os.Looper import android.os.Message import android.util.Log import com.example.asynctaskdemo.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private lateinit var binding:ActivityMainBinding private lateinit var myLooperThread: MyLooperThread private var myLooperThreadsLooper: Looper ?= null private var count = 0 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) Log.d("MainThread","Main thread ${Thread.currentThread().id}") myLooperThread = MyLooperThread() myLooperThread.start() val view = binding.root setContentView(view) binding.textView.text = "0" binding.btnStart.setOnClickListener{ Log.d("MainAct","Main thread ${mainLooper.thread.id}") val msg = Message() msg.obj = 2 myLooperThread.handler!!.handleMessage(msg) } binding.btnStop.setOnClickListener{ Log.d("MainAct","Main thread ${mainLooper.thread.id}") val msg = Message() msg.obj = 1 myLooperThread.handler!!.handleMessage(msg) } } }
自定义MyLooperThread类代码
package com.example.asynctaskdemo import android.os.Handler import android.os.Looper import android.os.Message import android.util.Log class MyLooperThread : Thread() { var handler: Handler ?= null override fun run() { Looper.prepare() handler = object : Handler(Looper.myLooper()!!) { override fun handleMessage(msg: Message) { // process incoming messages here Log.d("MyLooperThread","Looper Thread ID: ${Thread.currentThread().id}, message: ${msg.obj}") Log.d("MyLooperThread","Looper Thread ID: ${looper.thread.id}, message: ${msg.obj}") Log.d("MyLooperThread","Looper Thread is current: ${looper.isCurrentThread}, message: ${msg.obj}") if(Looper.myLooper() == Looper.getMainLooper()) Log.d("MyLooperThread","we are in main thread") else Log.d("MyLooperThread","we are in looper thread") } } Looper.loop() //Looper prepare() and loop() ensure that the thread doesnt die after running // run() just once. run () runs //indefinitely unless explicitly specified because of these functions } }
运行输出
D/MainAct: Main thread 2 D/MyLooperThread: Looper Thread ID: 2, message: 2 D/MyLooperThread: Looper Thread ID: 497, message: 2 D/MyLooperThread: Looper Thread is current: false, message: 2 D/MyLooperThread: we are in main thread
疑问解答
1. 为何输出显示处于主线程?即为何在MyLooperThread中声明Handler时,Looper.myLooper()与Looper.getMainLooper()相等?
问题出在消息发送的方式上:你没有通过Handler.sendMessage()将消息投递到子线程Looper的消息队列,而是直接在主线程的点击事件里同步调用了handler!!.handleMessage(msg)。这会让handleMessage方法直接在主线程执行,此时Looper.myLooper()获取的就是主线程的Looper,自然和Looper.getMainLooper()相等。
正确做法是调用handler!!.sendMessage(msg),让消息进入子线程Looper的消息队列,由Looper在子线程中取出并触发handleMessage。
2. looper.thread.id返回497,而Thread.currentThread().id返回2,二者有何区别?
looper.thread.id是自定义MyLooperThread的线程ID(497),因为这个Handler绑定的是该子线程的Looper。Thread.currentThread().id是当前执行handleMessage方法的线程ID,由于你直接在主线程调用handleMessage,所以这里返回主线程ID(2)。
如果改用sendMessage发送消息,Thread.currentThread().id就会和looper.thread.id一致,都是497。
3. 为何looper.isCurrentThread()返回false?
looper.isCurrentThread()用来判断当前执行代码的线程是否是Looper所属的线程。你的Handler绑定的是子线程(497)的Looper,但handleMessage是在主线程(2)执行的,当前线程和Looper所属线程不一致,所以返回false。
当你用sendMessage发送消息后,Looper会在子线程中处理消息,此时looper.isCurrentThread()就会返回true。
内容的提问来源于stack exchange,提问作者Parag
相关产品推荐
相关产品推荐

