0

我已经在 Thread、HandlerHandlerThread、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);
    }
}
4

1 回答 1

1

我使用调试器和检查元素的结论是,您无法在 handleMessage() 中确定是否正在处理消息或可运行对象。

我凭经验(通过消除)发现,当我将所有消息都设置为 msg.what 不是 0 时,我所有的 Runnables 都有一个 msg.what == 0。小心使用!

于 2013-06-17T19:15:05.237 回答