Androidサービスで、バックグラウンドタスクを実行するためのスレッドを作成しました。
スレッドがメインスレッドのメッセージキューに特定のタスクを投稿する必要がある状況があります。たとえば、Runnable
。
メインスレッドを取得して、他のスレッドから/にHandler
投稿する方法はありますか?Message
Runnable
Androidサービスで、バックグラウンドタスクを実行するためのスレッドを作成しました。
スレッドがメインスレッドのメッセージキューに特定のタスクを投稿する必要がある状況があります。たとえば、Runnable
。
メインスレッドを取得して、他のスレッドから/にHandler
投稿する方法はありますか?Message
Runnable
注:この回答は非常に注目されているため、更新する必要があります。元の回答が投稿されて以来、@dzeikeiからのコメントは元の回答とほぼ同じくらい注目されています。したがって、2つの可能な解決策があります。
1.バックグラウンドスレッドにContext
オブジェクトへの参照がある場合:
バックグラウンドワーカースレッドがコンテキストオブジェクト(アプリケーションコンテキストまたはサービスコンテキストの場合があります)にアクセスできることを確認してください。次に、バックグラウンドワーカースレッドでこれを実行します。
// Get a handler that can be used to post to the main thread
Handler mainHandler = new Handler(context.getMainLooper());
Runnable myRunnable = new Runnable() {
@Override
public void run() {....} // This is your code
};
mainHandler.post(myRunnable);
Context
2.バックグラウンドスレッドにオブジェクトがない(または必要ない)場合
(@dzeikeiによる提案):
// Get a handler that can be used to post to the main thread
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = new Runnable() {
@Override
public void run() {....} // This is your code
};
mainHandler.post(myRunnable);
以下のコメント投稿者が正しく指摘しているように、これはサービスの一般的なソリューションではなく、アクティビティから起動されたスレッドのみを対象としています(サービスはそのようなスレッドである可能性がありますが、すべてがそうであるとは限りません)。サービスとアクティビティのコミュニケーションの複雑なトピックについては、公式ドキュメントのサービスセクション全体をお読みください。複雑なので、基本を理解することをお勧めします:http: //developer.android.com/guide/components/services.html #通知
以下の方法は、最も単純な場合に機能する可能性があります。
私があなたを正しく理解しているなら、あなたはアプリケーションのGUIスレッドで実行されるいくつかのコードを必要とします(「メイン」スレッドと呼ばれる他のものについて考えることはできません)。このための方法がありますActivity
:
someActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
//Your code to run in GUI thread here
}//public void run() {
});
これがあなたが探しているものであることを願っています。
アクティビティをしているときは、
runOnUiThread {
//code that runs in main
}
アクティビティコンテキストがある場合、mContextは次に使用します
mContext.runOnUiThread {
//code that runs in main
}
コンテキストが利用できない場所にいる場合は、
Handler(Looper.getMainLooper()).post {
//code that runs in main
}
コンテキストへのアクセス権がない場合は、別の簡単な方法があります。
1)。メインルーパーからハンドラーを作成します。
Handler uiHandler = new Handler(Looper.getMainLooper());
2)。Runnableインターフェイスを実装します。
Runnable runnable = new Runnable() { // your code here }
3)。RunnableをuiHandlerに投稿します。
uiHandler.post(runnable);
以上です;-)スレッドを楽しんでください。ただし、スレッドを同期することを忘れないでください。
スレッドでコードを実行する場合、たとえば、アクションを遅らせる場合はrunOnUiThread
、コンテキストから呼び出す必要があります。たとえば、コードがMainActivity
クラス内にある場合は、次を使用します。
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
myAction();
}
});
メソッドをメイン(UIスレッド)または他のスレッドから呼び出すことができる場合は、次のようなチェックが必要です。
public void myMethod() {
if( Looper.myLooper() == Looper.getMainLooper() ) {
myAction();
}
else {
}
要約されたコードブロックは次のとおりです。
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
// things to do on the main thread
}
});
これには、アクティビティ参照またはアプリケーション参照の受け渡しは含まれません。
Kotlin相当:
Handler(Looper.getMainLooper()).post(Runnable {
// things to do on the main thread
})
特にコンテキストがない場合、RxAndroidを使用している場合、最も簡単な方法は次のようになります。
AndroidSchedulers.mainThread().scheduleDirect {
runCodeHere()
}
ハンドラーを使用したより正確なKotlinコード:
Handler(Looper.getMainLooper()).post {
// your codes here run on main Thread
}
私が考えることができる1つの方法はこれです:
1)UIをサービスにバインドします。
2)以下のようなメソッドを公開しBinder
ますHandler
。
public void registerHandler(Handler handler) {
mHandler = handler;
}
3)UIスレッドで、サービスにバインドした後、上記のメソッドを呼び出します。
mBinder.registerHandler(new Handler());
4)サービスのスレッドのハンドラーを使用して、タスクを投稿します。
mHandler.post(runnable);
HandlerThread
Androidの通常のJavaスレッドよりも優れたオプションです。
requestHandler
post
上のRunnable
タスクrequestHandler
からのUIスレッドとの通信HandlerThread
Handler
withを作成します:そしてoverrideメソッドLooper
responseHandler
handleMessage
Runnable
他のスレッド(HandlerThread
この場合)のタスク内で、呼び出しsendMessage
ますresponseHandler
sendMessage
結果、inが呼び出さhandleMessage
れresponseHandler
ます。Message
処理し、UIを更新します例TextView
: Webサービスから受信したデータで更新します。WebサービスはUI以外のスレッドで呼び出す必要があるHandlerThread
ため、ネットワーク操作用に作成されます。Webサービスからコンテンツを取得したら、メインスレッド(UIスレッド)ハンドラーにメッセージを送信します。メインスレッドHandler
はメッセージを処理し、UIを更新します。
サンプルコード:
HandlerThread handlerThread = new HandlerThread("NetworkOperation");
handlerThread.start();
Handler requestHandler = new Handler(handlerThread.getLooper());
final Handler responseHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
txtView.setText((String) msg.obj);
}
};
Runnable myRunnable = new Runnable() {
@Override
public void run() {
try {
Log.d("Runnable", "Before IO call");
URL page = new URL("http://www.your_web_site.com/fetchData.jsp");
StringBuffer text = new StringBuffer();
HttpURLConnection conn = (HttpURLConnection) page.openConnection();
conn.connect();
InputStreamReader in = new InputStreamReader((InputStream) conn.getContent());
BufferedReader buff = new BufferedReader(in);
String line;
while ((line = buff.readLine()) != null) {
text.append(line + "\n");
}
Log.d("Runnable", "After IO call:"+ text.toString());
Message msg = new Message();
msg.obj = text.toString();
responseHandler.sendMessage(msg);
} catch (Exception err) {
err.printStackTrace();
}
}
};
requestHandler.post(myRunnable);
役立つ記事:
handlerthreads-and-why-you-should-be-using-them-in-your-android-apps
これは古い質問ですが、KotlinとJavaの両方で使用しているメインスレッドのワンライナーに出くわしました。これはサービスにとって最善の解決策ではないかもしれませんが、フラグメント内のUIを変更する何かを呼び出す場合、これは非常に単純で明白です。
Java(8):
getActivity().runOnUiThread(()->{
//your main thread code
});
Kotlin:
this.runOnUiThread {
//your main thread code
}
したがって、最も便利なのは、次のようなことを行うことです。
import android.os.AsyncTask
import android.os.Handler
import android.os.Looper
object Dispatch {
fun asyncOnBackground(call: ()->Unit) {
AsyncTask.execute {
call()
}
}
fun asyncOnMain(call: ()->Unit) {
Handler(Looper.getMainLooper()).post {
call()
}
}
}
以降:
Dispatch.asyncOnBackground {
val value = ...// super processing
Dispatch.asyncOnMain { completion(value)}
}
ContextCompat.getMainExecutor(context).execute {
// do something
}
この方法に従ってください。この方法を使用すると、バックグラウンドスレッドからUIを簡単に更新できます。runOnUiThreadは、main(UI)スレッドで動作します。このコードスニペットは、特に初心者にとってはそれほど複雑で簡単ではないと思います。
AsyncTask.execute(new Runnable() {
@Override
public void run() {
//code you want to run on the background
someCode();
//the code you want to run on main thread
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
/*the code you want to run after the background operation otherwise they will executed earlier and give you an error*/
executeAfterOperation();
}
});
}
});
サービスの場合
oncreateでハンドラーを作成します
handler = new Handler();
次に、このように使用します
private void runOnUiThread(Runnable runnable) {
handler.post(runnable);
}
Kotlinの場合、Anko corountinesを使用できます:
アップデート
doAsync {
...
}
非推奨
async(UI) {
// Code run on UI thread
// Use ref() instead of this@MyActivity
}
public void mainWork() {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
//Add Your Code Here
}
});
}
これは、サービスクラスでも問題なく機能します。
Kotlinを使用すると、関数内では次のようになります。
runOnUiThread {
// Do work..
}