2011-05-31 55 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