从服务访问UI线程处理程序

时间:2011-06-16 08:53:02

标签: android multithreading user-interface service handler

我在Android上尝试新的东西,我需要访问UI线程的处理程序。

我知道以下内容:

  1. UI线程有自己的处理程序 和looper
  2. 将放置任何消息 进入UI的消息队列 线程
  3. looper接受了这个事件 并将其传递给处理程序
  4. 处理程序处理消息和 将特定事件发送到UI
  5. 我希望我的服务必须获取UI线程处理程序并将消息放入此处理程序。 这样就可以处理此消息并将其发布到UI。 这里的服务将是一个正常的服务,将由一些应用程序启动。

    我想知道这是否可行。 如果是这样,请建议一些代码片段,以便我可以尝试。

    此致 吉里什

7 个答案:

答案 0 :(得分:172)

这段代码构造了与主(UI)线程关联的处理程序:

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

然后您可以在主(UI)线程中发布要执行的内容,如下所示:

handler.post(runnable_to_call_from_main_thread);

如果处理程序本身是从主(UI)线程创建的,为简洁起见,可省略参数:

Handler handler = new Handler();

进程和线程上的Android Dev Guide有更多信息。

答案 1 :(得分:28)

创建一个附加到Messenger的{​​{1}}对象,并将Handler传递给Messenger(例如,Service Intent的额外内容})。然后,startService()可以通过ServiceMessage发送HandlerHere is a sample application证明了这一点。

答案 2 :(得分:4)

目前我更喜欢使用Otto这样的事件总线库来解决这类问题。只需订阅所需的组件(活动):

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

然后提供回调方法:

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

然后当您的服务执行如下语句时:

bus.post(new TimeLeftEvent(340));

该POJO将传递给您的上述活动和所有其他订阅组件。简单而优雅。

答案 3 :(得分:2)

您可以通过广播接收器获取值......如下所示,首先创建您自己的IntentFilter,

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

然后创建内部类BroadcastReceiver as,

    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()中注册您的广播接收器,

registerReceiver(broadcastReceiver, intentFilter);

最后在onDestroy()中取消注册BroadcastReceiver,

unregisterReceiver(broadcastReceiver);

现在最重要的部分......你需要从需要发送值的地方发射广播.....所以这样做,

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

....欢呼:)

答案 4 :(得分:0)

解决方案:

  1. 使用主线程中的Handler创建Looper:requestHandler
  2. 使用主线程中的Handler创建Looper:responseHandler并覆盖handleMessage方法
  3. 在requestHandler上发布Runnable任务
  4. Runnable内部任务中,在responseHandler
  5. 上调用sendMessage
  6. 在responseHandler中调用handleMessage的sendMessage结果。
  7. Message获取属性并对其进行处理,更新用户界面
  8. 示例代码:

        /* 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);
        }
    

答案 5 :(得分:0)

kotlin中,您可以做到

假设您要显示来自服务的Toast消息

val handler = Handler(Looper.getMainLooper())
handler.post {
   Toast.makeText(context, "This is my message",Toast.LENGTH_LONG).show()
}

答案 6 :(得分:0)

我建议尝试以下代码:

    new Handler(Looper.getMainLooper()).post(() -> {

        //UI THREAD CODE HERE



    });