2011-06-16 112 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); 
    }