Androidサービスで、バックグラウンドタスクを実行するためのスレッドを作成しました。
スレッドがメインスレッドのメッセージキューに特定のタスクを投稿する必要がある状況があります。 Runnable
。
Handler
メインスレッドを取得して投稿する方法はありますかMessage
/Runnable
私の他のスレッドから、それには?
おかげで、
Androidサービスで、バックグラウンドタスクを実行するためのスレッドを作成しました。
スレッドがメインスレッドのメッセージキューに特定のタスクを投稿する必要がある状況があります。 Runnable
。
Handler
メインスレッドを取得して投稿する方法はありますかMessage
/Runnable
私の他のスレッドから、それには?
おかげで、
回答:
注:この回答は非常に注目されているため、更新する必要があります。元の回答が投稿されてから、@ dzeikeiからのコメントは、元の回答とほぼ同じくらい注目されました。だからここに2つの可能な解決策があります:
1.バックグラウンドスレッドにContext
オブジェクトへの参照がある場合:
バックグラウンドワーカースレッドが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);
2.バックグラウンドスレッドにContext
オブジェクトがない(または必要でない)場合
(@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);
Handler
(またはHandler.Callback
インターフェースを使用)するhandleMessage()
場合、メソッドはハンドラーを使用して投稿されたメッセージに対してのみ呼び出されます。メインスレッドはメッセージをポスト/処理するために別のハンドラーを使用しているため、競合は発生しません。
Handler mainHandler = new Handler(Looper.getMainLooper());
new Runnable(){@Override public void run() {....}};
以下のコメンターが正しく指摘しているように、これはサービスの一般的な解決策ではなく、アクティビティから起動されたスレッドに対してのみです(サービスはそのようなスレッドである場合がありますが、すべてではありません)。サービスとアクティビティの通信の複雑なトピックについては、公式ドキュメントの「サービス」セクション全体をお読みください。複雑なので、基本を理解するのにお金がかかります。http: //developer.android.com/guide/components/services.html #Notifications
以下の方法は、単純なケースで機能する場合があります。
私があなたを正しく理解している場合、アプリケーションのGUIスレッドで実行されるいくつかのコードが必要です(「メイン」スレッドと呼ばれる他のものについては考えられません)。このためのメソッドがありActivity
ます:
someActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
//Your code to run in GUI thread here
}//public void run() {
});
ドキュメント:http : //developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29
これがあなたが探しているものであることを願っています。
Service
ます。あなたは使用することはできませんrunOnUiThread()
でService
。この回答は誤解を招くものであり、尋ねられた質問には対応していません。
コンテキストにアクセスできない場合は、別の簡単な方法があります。
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 {
}
Service
ます。あなたは使用することはできませんrunOnUiThread()
でService
。
Activity
ドキュメントへのリンクで示したようにrunOnUiThread()
、のメソッドですActivity
。の方法ではないService
ため、使用できません。それより何がはっきりしているのでしょうか?
あなたが活動しているときに、使用してください
runOnUiThread {
//code that runs in main
}
ときあなたはアクティビティコンテキストを持って、mContextは、使用します
mContext.runOnUiThread {
//code that runs in main
}
あなたはどこかにいるときはありませんコンテキスト利用でき、その後、使用
Handler(Looper.getMainLooper()).post {
//code that runs in main
}
runOnUiThread(){...}
特にコンテキストがない場合、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 Looper
for main thread: responseHandler
およびオーバーライドhandleMessage
メソッドを作成しますRunnable
(他のスレッドのタスクHandlerThread
この場合)、呼び出しsendMessage
にresponseHandler
sendMessage
結果、が呼び出さ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);
役立つ記事:
この方法に従ってください。この方法を使用すると、単にバックグラウンドスレッドから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
}
したがって、最も便利なのは次のようなことです。
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)}
}