私はUIスレッドのハンドラーにアクセスする必要があるAndroidで新しいことを試みています。
私は次のことを知っています:
UIスレッドハンドラーを取得し、このハンドラーにメッセージを挿入する必要があるサービスが必要です。そのため、このメッセージは処理され、UIに発行されます。ここでは、サービスは、何らかのアプリケーションによって開始される通常のサービスになります。
これが可能かどうか知りたいです。もしそうなら、私はそれを試すことができるように、いくつかのコードスニペットを提案してください。
よろしくGirish
このコードスニペットは、メイン(UI)スレッドに関連付けられたハンドラーを構築します。
Handler handler = new Handler(Looper.getMainLooper());
その後、次のようにメイン(UI)スレッドに実行用のものを投稿できます。
handler.post(runnable_to_call_from_main_thread);
ハンドラー自体がメイン(UI)スレッドから作成される場合、簡潔にするために引数を省略できます。
Handler handler = new Handler();
プロセスとスレッドの Android Dev Guide に詳細があります。
Messenger
にアタッチされたHandler
オブジェクトを作成し、そのMessenger
をService
に渡します(たとえば、startService()
)。 Service
は、Message
を介してHandler
にMessenger
を送信できます。 これはサンプルアプリケーションです これを示しています。
現時点では、この種の問題には Otto などのイベントバスライブラリを使用することを好みます。目的のコンポーネント(アクティビティ)をサブスクライブするだけです。
protected void onResume() {
super.onResume();
bus.register(this);
}
次に、コールバックメソッドを提供します。
public void onTimeLeftEvent(TimeLeftEvent ev) {
// process event..
}
そして、サービスが次のようなステートメントを実行するとき:
bus.post(new TimeLeftEvent(340));
そのPOJOは、上記のアクティビティと他のすべてのサブスクライブコンポーネントに渡されます。シンプルでエレガント。
ブロードキャストレシーバーを介して値を取得できます......次のように、まず独自のIntentFilterを作成し、
Intent intentFilter=new IntentFilter();
intentFilter.addAction("YOUR_INTENT_FILTER");
次に、内部クラスBroadcastReceiverを次のように作成します。
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);
.... cheers :)
次のコードを試すことをお勧めします。
new Handler(Looper.getMainLooper()).post(() -> {
//UI THREAD CODE HERE
});
kotlin
では、それがどのようにできるのか
サービスからのトーストメッセージを表示する場合は発言しましょう
val handler = Handler(Looper.getMainLooper())
handler.post {
Toast.makeText(context, "This is my message",Toast.LENGTH_LONG).show()
}
解決:
Handler
を使用してLooper
を作成します:responseHandlerおよびhandleMessage
メソッドをオーバーライドしますRunnable
タスク内で、responseHandlerでsendMessageを呼び出しますsendMessage
結果は、responseHandlerのhandleMessageの呼び出しを行います。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);
}