我已经在 Thread、Handler、HandlerThread、Looper 以及 SO 上搜索了 java API,但找不到答案。当然,我还使用 Eclipse 的调试器来单步检查我的“味精”。
情况:handleMessage(Message msg)
如果您通过只允许一个工作线程访问它来保护您的数据模型免受并发问题的影响,那么如果您将消息和 Runnable 都排入同一消息队列中,您将如何区分其中的 Runnable 和 Message呢?
问:虽然我的 Runnable 在通过 发布后按计划执行handler.postDelayed(myRunnable)
,但我想在我的工作线程正在切换时检查 Runnable 的内容,以便我可以适当地更新我的数据模型。
我欢迎所有反馈并感谢您的时间!
下面是 Ecipe 调试器中显示的“msg”的全部内容。这里是否有足够的信息来打开 Runnable?
msg Message (id=830030887816)
arg1 0
arg2 0
callback null
data Bundle (id=830030968104)
mAllowFds true
mClassLoader BootClassLoader (id=830023329296)
packages HashMap (id=830023329320)
parent null
mFdsKnown true
mHasFds false
mMap HashMap (id=830030980304)
mParcelledData null
flags 1
next null
obj null
replyTo null
target IncomingHandler (id=830031033176)
what 0
when 180369888
下面是我的工作线程的handleMessage()。具体来说,我将一个 HandlerThread 实例化为我的工作线程,并将它的 getLooper() 绑定到我的工作线程 Handler。
@Override
public void handleMessage(Message msg) {
// If this is a Runnable then I need to call my method.
// This next line is a hack to test for Runnable.
// I would like to know how to inspect this Runnable
if (0 == msg.arg2 && 0 == msg.arg1 && 0 == msg.what)
incrementStateMachineBecauseRunnableStarted();
// Determine which action to take
// http://stackoverflow.com/questions/5021246/conveniently-map-between-enum-and-int-string
switch (Cmd.values()[msg.what]) {
case RECEIVE_NEW_LIST_EMPLOYEES:
receiveNewListEmployees(msg);
break;
case UPDATE_ONE_EMPLOYEE_STATE:
updateOneEmployeeState(msg);
break;
default:
Log.e(this.getClass().getName(), "unexpected message.";
break;
}
这就是我将 Runnable 排入队列的方式(我在我的工作线程上运行此代码,因此它正在向自己发送一条消息,以便稍后处理handleMessage(Message msg)
):
// Create a new Runnable for this employee
PostUpdate update = new PostUpdate(employee);
// Post this Runnable with a sort delay
postDelayed(update, WAIT_BEFORE_PUSH_MS);
...这就是我将消息排入队列的方式(来自另一个线程):
Message msg = mHandler.obtainMessage();
msg.what = Cmd.RECEIVE_NEW_LIST_EMPLOYEES.ordinal();
msg.arg1 = 77; // deliberately inserting debug value
Bundle bundle = new Bundle();
bundle.putParcelableArrayList(Cmd.RECEIVE_NEW_LIST_EMPLOYEES.toString(), mEmployees);
msg.setData(bundle);
mHandler.sendMessage(msg);
最后,我的 Runnable:
private class PostUpdate implements Runnable {
private final Employee mEmployee;
public PostUpdate(Employee employee) {
mEmployee = employee;
}
@Override
public void run() {
// Post update through network to MySql server
mDao.setState(mEmployee);
}
}