Android:如何接管Activity的消息循环,如Win32中的GetMessage / PostMessage?

时间:2011-05-31 08:24:05

标签: android android-activity modal-dialog message-queue

我最初的目标是建立自己的模态对话框。在某些时候,我必须运行一个内部循环,这将非常接近Win32中的GetMessage / PostMessage,如果你有Win32经验,那么你对此非常熟悉。 内部循环将阻止当前工作流但仍处理事件。伪代码就像,

private void doModal() {

    doSth();

    // start loop and process events
    while (!isQuit) {
        Message msg = nextMessage();

        // process all wanted msgs, and simply discard all unexpected msgs
        if (isWantedMsg) {
            sendToTarget(msg);
        }
    }
}

我查看了源代码,Looper.loop(),这是

public static final void loop() {
    Looper me = myLooper();
    MessageQueue queue = me.mQueue;
    while (true) {
        Message msg = queue.next(); // might block
        if (msg != null) {
            if (msg.target == null) {
                // No target is a magic identifier for the quit message.
                return;
            }
            msg.target.dispatchMessage(msg);
            msg.recycle();
        }
    }
}

基本上我想写这样一个循环,然后我就能够接收所有的消息并处理或丢弃它们。不幸的是,MessageQueue属于android.os包,我没有权限访问它的大部分接口。 Activity.dispatchTouchEvent只是一个处理程序,而不是我的情况。

我该怎么办?感谢。

========================== SOLUTION ==================== =================
我通过反射解决了它,我完全复制了Looper.loop()的源代码,见下文,

private void startModal() {
    Class clsMsgQueue = null;
    Method nextMethod = null;
    Class clsMsg = null;

    mQuitModal = false;

    MessageQueue queue = Looper.myQueue();
    clsMsgQueue = queue.getClass();
    try {
        nextMethod = clsMsgQueue.getDeclaredMethod("next", new Class[]{});
    } catch (SecurityException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    nextMethod.setAccessible(true);

    while (!mQuitModal) {

            Message msg = null;
            try {
                msg = (Message)nextMethod.invoke(queue, new Object[]{});
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            if (msg != null) {
                clsMsg = msg.getClass();
                Field targetFiled = null;
                try {
                    targetFiled = clsMsg.getDeclaredField("target");
                } catch (SecurityException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (NoSuchFieldException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                targetFiled.setAccessible(true);

                Handler target = null;
                try {
                    target = (Handler) targetFiled.get(msg);
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                if (target == null) {
                    // No target is a magic identifier for the quit message.
                    mQuitModal = true;
                }

                target.dispatchMessage(msg);

                msg.recycle();
            }
        }
    }

当对话框被解除时,mQuitModal也设置为true。

如果不关心性能问题,那就有用了。

1 个答案:

答案 0 :(得分:2)

抱歉,Android故意不支持这样的嵌套事件循环。您只需要以不同的方式构建代码 - 对于对话框,您通常会启动对话框,返回事件循环,并实现回调以处理来自它的结果。