Google关于绑定服务的文档正在推广using a Messenger
in lieu of your own custom binding for IPC。因此,我尝试尝试a particular experiment that I am running。
但是,Messenger
需要一个Handler
。如今,Handler
需要一个Looper
,在这种情况下,无论如何我都可能想要一个作为后台线程(与Looper.getMainLooper()
相对)。我唯一知道的另一种Looper
是run()
和HandlerThread
并从中获得Looper
。
the deprecated non-Looper
forms of the Handler
constructor的文档包括:
在Handler构造过程中过分选择Looper可能会导致以下错误:操作无提示地丢失操作(如果Handler不期望新任务并退出),崩溃(如果有时在未激活Looper的线程上创建了处理程序),或竞争条件,处理程序与之关联的线程不是作者预期的。 相反,请使用Executor或使用Looper#getMainLooper,View#getHandler或类似工具显式指定Looper。
(添加了重点)
这是措辞奇怪的文档,还是存在使Looper
或Handler
与我似乎找不到的Executor
绑定的秘诀?
答案 0 :(得分:1)
我认为他们的意思是建议使用Executor
而不是Handler
。我不知道有Executor
支持的任何Looper
实现。
使用
Handler
或类似的方法代替Executor
,而使用Looper
或明确指定Looper#getMainLooper
。 >
仅在需要运行View#getHandler
时有用。例如,CameraManager.openCamera()方法在API级别28处有重载。
此方法的行为与
Runable
的行为匹配,不同之处在于它使用openCamera(java.lang.String, StateCallback, android.os.Handler)
作为参数而不是Executor
。
如果您需要Handler
,则始终必须提供Messenger
支持的Hanlder
,Looper
,Looper.getMainLooper()
已解决或通过Looper.myLooper()
。
或者,您可以创建一个HandlerThread
并在其上运行loop()
。但这基本上就是Looper
所做的。
答案 1 :(得分:1)
更新:TL; DR
// Check if this thread already has prepared a looper
if (Looper.myLooper() == null) {
Looper.prepare()
}
val threadHandler = Handler(Looper.myLooper())
val messenger = Messenger(threadHandler)
messenger.send(...)
长期回答
如果您想进一步了解正在发生的事情以及每段代码在哪个线程中运行:
// Check if this thread already has prepared a looper
// Running on Original Thread
if (Looper.myLooper() == null) {
Looper.prepare()
}
// Save thread's Looper (1)
// Running on Original Thread
val threadLooper = Looper.myLooper()
Handler(Looper.getMainLooper()).post {
// Do some UI stuff, for instance, show a dialog
// Running on UI Thread
AlertDialog
.Builder(context)
.setTitle("Dialog title")
.setMessage("Dialog message")
.setNegativeButton("Cancel") { _: DialogInterface, _: Int ->
// Use thread's Looper from (1) to notify the original thread
// Running on UI Thread
Handler(threadLooper).post {
// Running on Original Thread
callback?.onCancel()
}
}
.setPositiveButton("Retry") { _: DialogInterface, _: Int ->
// Use thread's Looper from (1) to notify the original thread
// Running on UI Thread
Handler(threadLooper).post {
// Running on Original Thread
callback?.onRetry()
}
}
.show()
}
// Call loop() to start the thread's loop
// Running on Original Thread
Looper.loop()