2011-05-31 47 views
0

我最初的目标是建立我自己的模态对话框。在某些时候,我必须运行一个内部循环,如果你有Win32的经验,那么你会非常熟悉Win32中的GetMessage/PostMessage。 内部循环将阻止当前工作流程,但仍处理事件。的伪代码会是什么样子,Android:如何接管Activity的消息循环,如Win32中的GetMessage/PostMessage?

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只是一个处理程序,而不是我的情况。

我该怎么办?谢谢。

==========================解决方法=================== ==================
我通过反射解决它,我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。

如果不太关心性能问题,它就起作用了。

+0

简而言之,没有专业的开发人员应该使用此代码。 – CommonsWare 2011-06-02 17:17:21

+0

我正在为Android构建调试器,并且需要在UI线程(用于断点)上暂停时处理UI事件。这段代码正是我所需要的。但是,我应该指出,msg.recycle不起作用,您需要调用'recycleUnchecked'。 – irbull 2016-03-03 22:45:44

回答

2

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

+0

Thx。我已经通过反思解决了它,检查了我的第一篇文章。 – fifth 2011-05-31 10:34:56

+1

您的解决方案是BROKEN。任何使用该应用程序编写应用程序的人都可能希望他们的应用程序崩溃我们不会试图让它工作。 – hackbod 2011-06-02 04:33:30