2011-06-16 110 views
78

我想了解一些我需要訪問UI線程的處理程序的新東西。從服務中訪問UI線程處理程序

我瞭解以下內容:

  1. 的UI線程都有自己的處理程序 和下線
  2. 任何消息將投入 到UI 線程的消息隊列
  3. 彎針回升事件 並將其傳遞給處理程序
  4. 處理程序處理該消息,並且 將特定事件發送到UI

我想要我的服務必須獲得UI線程處理程序並將消息放入此處理程序。 因此,這條消息將被處理併發布到UI。 這裏的服務將是一個正常的服務,將由一些應用程序啓動。

我想知道這是否可能。 如果是這樣,請提供一些代碼片段,以便我可以嘗試。

問候 吉里什

回答

27

創建附加到一個Handler對象Messenger並傳遞MessengerService(例如,在一個Intent額外的startService())。 Service然後可以通過Messenger發送MessageHandlerHere is a sample application證明了這一點。

+0

感謝這個提示。這很有幫助。請看下面的堆棧觸摸事件流到我的活動 MyDemo.dispatchTouchEvent(MotionEvent)行:20 PhoneWindow $ DecorView.dispatchTouchEvent(MotionEvent)線:1696 ViewRoot.handleMessage(消息)線:1658 的ViewRoot(處理器) .dispatchMessage(消息)行:99 Looper.loop()line:123 //事件處理從這裏開始 ActivityThread.main(String [])line:4203 這裏ViewRoot是一個Handler。我想獲得這個處理程序的參考...是否有可能從我的應用程序中獲取? – iLikeAndroid 2011-06-21 06:04:30

+0

@iLikeAndroid:如果你沒有創建'Handler',你不能訪問它,AFAIK。 – CommonsWare 2011-06-21 11:41:21

+0

謝謝。我試圖創建一個ViewRoot的實例。這不過是一個處理程序。現在我可以在這個處理程序上發出消息。處理程序正在收到消息。但ViewRoot無法處理該消息,因爲它未正確初始化。我需要調用ViewRoot.setView()將適當的數據初始化爲ViewRoot。我想知道是否有默認視圖或基礎視圖等,我可以用它來初始化? – iLikeAndroid 2011-06-21 14:50:19

158

的這段代碼構造與主(UI)線程相關的處理程序:

Handler handler = new Handler(Looper.getMainLooper()); 

然後,您可以發佈的東西在主(UI)執行線程像這樣:

handler.post(runnable_to_call_from_main_thread); 

如果處理程序本身是從主(UI)線程創建的,則爲簡潔起見可省略參數:

Handler handler = new Handler(); 

關於進程和線程的Android Dev Guide有更多信息。

+2

經過測試,效果很好! 用例的示例:我有一個Web界面,由直接在設備上運行的服務器提供服務。由於該接口可用於直接與UI進行交互,並且由於服務器需要在其自己的線程上運行,因此我需要一種方法來從Activity外部觸摸UI線程。你所描述的方法工作得很好。 – mrPjer 2012-06-19 20:53:39

+1

輝煌。像魅力一樣工作,非常有用。謝謝。 – JRun 2013-08-02 13:29:59

+0

完美^^只是用它來更新從StreamingService我的用戶界面。正是我需要的感謝! – 2014-01-15 09:53:09

4

目前我更喜歡使用事件總線庫,例如Otto這類問題。只要訂閱所需的成分(活性):

protected void onResume() { 
    super.onResume(); 
    bus.register(this); 
} 

然後提供一個回調方法:

public void onTimeLeftEvent(TimeLeftEvent ev) { 
    // process event.. 
} 

,然後當你的服務執行這樣的語句:

bus.post(new TimeLeftEvent(340)); 

這POJO會傳遞給您的上述活動和所有其他訂閱組件。簡單而優雅。

2

你可以得到通過廣播接收器值......如下,首先建立自己的IntentFilter如,

Intent intentFilter=new IntentFilter(); 
intentFilter.addAction("YOUR_INTENT_FILTER"); 

然後創建內部類廣播接收器的,

private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { 
    /** Receives the broadcast that has been fired */ 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     if(intent.getAction()=="YOUR_INTENT_FILTER"){ 
      //HERE YOU WILL GET VALUES FROM BROADCAST THROUGH INTENT EDIT YOUR TEXTVIEW/////////// 
      String receivedValue=intent.getStringExtra("KEY"); 
     } 
    } 
}; 

現在註冊您的廣播接收器在onResume()as,

registerReceiver(broadcastReceiver, intentFilter); 

最後取消註冊BroadcastRec eiver中的onDestroy()的,

unregisterReceiver(broadcastReceiver); 

現在最重要的部分......你需要火從任何地方你需要發送值廣播.....這樣做的,

Intent i=new Intent(); 
i.setAction("YOUR_INTENT_FILTER"); 
i.putExtra("KEY", "YOUR_VALUE"); 
sendBroadcast(i); 

....歡呼:)

0

解決方案:

  1. 創建Looper從主線程一個Handler:requestHa ndler
  2. 從主線程創建Looper一個Handler:ResponseHandler所和覆蓋handleMessage方法
  3. 張貼在requestHandler
  4. 一個Runnable任務裏面Runnable任務,調用的sendMessage上ResponseHandler所
  5. 在ResponseHandler所的handleMessage這sendMessage結果調用。
  6. Message並處理它獲取的屬性,更新UI

示例代碼:

/* Handler from UI Thread to send request */ 

    Handler requestHandler = new Handler(Looper.getMainLooper()); 

    /* Handler from UI Thread to process messages */ 

    final Handler responseHandler = new Handler(Looper.getMainLooper()) { 
     @Override 
     public void handleMessage(Message msg) { 

      /* Processing handleMessage */ 

      Toast.makeText(MainActivity.this, 
        "Runnable completed with result:"+(String)msg.obj, 
        Toast.LENGTH_LONG) 
        .show(); 
     } 
    }; 

    for (int i=0; i<10; i++) { 
     Runnable myRunnable = new Runnable() { 
      @Override 
      public void run() { 
       try { 
        /* Send an Event to UI Thread through message. 
         Add business logic and prepare message by 
         replacing example code */ 

        String text = "" + (++rId); 
        Message msg = new Message(); 

        msg.obj = text.toString(); 
        responseHandler.sendMessage(msg); 
        System.out.println(text.toString()); 

       } catch (Exception err) { 
        err.printStackTrace(); 
       } 
      } 
     }; 
     requestHandler.post(myRunnable); 
    }