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

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

我知道如下:

  1. UI 线程有自己的处理程序 还有环形装置
  2. 任何消息都会被放上去 进入用户界面的消息队列 线
  3. 环形使者接收事件 然后传给了管理员
  4. 处理程序处理消息和 将特定事件发送到 UI

我想有我的服务,必须得到 UI 线程处理程序,并把一个消息到这个处理程序。 以便处理此消息并将其发送给 UI。 这里的服务将是由某个应用程序启动的普通服务。

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

问候 娘娘腔

82744 次浏览

Create a Messenger object attached to your Handler and pass that Messenger to the Service (e.g., in an Intent extra for startService()). The Service can then send a Message to the Handler via the Messenger. Handler0 demonstrating this.

This snippet of code constructs a Handler associated with the main (UI) thread:

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

You can then post stuff for execution in the main (UI) thread like so:

handler.post(runnable_to_call_from_main_thread);

If the handler itself is created from the main (UI) thread the argument can be omitted for brevity:

Handler handler = new Handler();

The Android Dev Guide on processes and threads has more information.

At the moment I prefer using event bus library such as Otto for this kind of problem. Just subscribe the desired components (activity):

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

Then provide a callback method:

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

and then when your service execute a statement like this:

bus.post(new TimeLeftEvent(340));

That POJO will be passed to your above activity and all other subscribing components. Simple and elegant.

You can get values through broadcast receiver......as follows, First create your own IntentFilter as,

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

Then create inner class 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");
}
}
};

Now Register your Broadcast receiver in onResume() as,

registerReceiver(broadcastReceiver, intentFilter);

And finally Unregister BroadcastReceiver in onDestroy() as,

unregisterReceiver(broadcastReceiver);

Now the most important part...You need to fire the broadcast from wherever you need to send values..... so do as,

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

....cheers :)

Solution:

  1. Create a Handler with Looper from Main Thread : requestHandler
  2. Create a Handler with Looper from Main Thread: responseHandler and override handleMessage method
  3. post a Runnable task on requestHandler
  4. Inside Runnable task, call sendMessage on responseHandler
  5. This sendMessage result invocation of handleMessage in responseHandler.
  6. Get attributes from the Message and process it, update UI

Sample code:

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

In kotlin thats how you can do it

Let say if you want to show Toast message from service

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

I suggest trying following code:

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


//UI THREAD CODE HERE






});