用 Looper.getMainLooper() 初始化的处理程序不响应消息回调
Posted
技术标签:
【中文标题】用 Looper.getMainLooper() 初始化的处理程序不响应消息回调【英文标题】:Handlers initialized with Looper.getMainLooper() does not respond to message callbacks 【发布时间】:2013-03-10 09:59:45 【问题描述】:我正在尝试实现从不同线程监听同一个 Looper 的处理程序。
下面我有两个处理程序,一个在主线程中创建,另一个在子线程中创建,但是两者都被初始化为在 Main Looper 上侦听。
private Handler mMain;
public static final ThreadPoolExecutor tpe =
(ThreadPoolExecutor) Executors.newCachedThreadPool();
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMain = new Handler(Looper.getMainLooper())
@Override
public void handleMessage(Message msg)
Log.wtf("", "main:" + msg);
;
tpe.execute(new Runnable()
private Handler tChild = new Handler(Looper.getMainLooper())
@Override
public void handleMessage(Message msg)
Log.wtf("", "child:" + msg);
;
@Override
public void run()
Log.wtf("", "send msg to main looper");
tChild.sendEmptyMessage(100);
);
但是当我发送如下消息时,只有子处理程序会打印消息。主处理程序没有收到消息。
03-20 22:02:26.754: A/(12857): send msg to main looper
03-20 22:02:26.847: A/(12857): child: what=100 when=-8ms
我做错了什么?感谢您的阅读。
【问题讨论】:
【参考方案1】:每个Handler
实例都控制Message
目标,无法让它们共享,因此发送到Handler
的每条消息或帖子都只能由该实例执行。
Looper
表示哪个线程发送的消息/runnables 将在哪个线程上执行。在您的代码中,两个处理程序都将在主线程上执行handleMessage()
,尽管它们是在单独的线程上创建的。这就是你可以将Looper
实例传递给Handler
的真正原因...如果你没有传递Looper
,那么Handler
将在它所在的线程上执行代码已创建(必须也是Looper
线程)。
此外,因此没有理由创建多个处理程序以这种方式发布数据。单个Handler
被设计为从多个线程发送消息,它们都在MessageQueue
中序列化并在选定的Looper
线程上执行。您可以从后台线程直接发布到mMain
以在该线程上执行代码。在这种情况下,传递Looper
是多余的,因为代码已经在主线程上。
【讨论】:
我明白了,谢谢!假设有一天 Runnable 是一个外部类而不是一个内部类,我应该通过它的构造函数将一个初始化的 Handler 传递给它,对吧? 架构将依赖于应用程序,但您需要从计划向其发布消息的任何位置引用Handler
。
为什么不在Application上下文(扩展Application的类)中只使用一个Handler(this.getMainLooper())?这难道不会比在 Activity 中进行更清洁吗?【参考方案2】:
发送到Handler
的消息将仅由该Handler
处理,即使它正在共享Looper
。
Handler的源码中埋藏着一行
msg.target = this;
这确保没有其他Handler
会碰它。
【讨论】:
以上是关于用 Looper.getMainLooper() 初始化的处理程序不响应消息回调的主要内容,如果未能解决你的问题,请参考以下文章
Android 判断当前thread 是否是UI thread