368

Androidサービスで、バックグラウンドタスクを実行するためのスレッドを作成しました。

スレッドがメインスレッドのメッセージキューに特定のタスクを投稿する必要がある状況があります。たとえば、Runnable

メインスレッドを取得して、他のスレッドから/にHandler投稿する方法はありますか?MessageRunnable

4

17 に答える 17

681

注:この回答は非常に注目されているため、更新する必要があります。元の回答が投稿されて以来、@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);

Context2.バックグラウンドスレッドにオブジェクトがない(または必要ない)場合

(@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);
于 2012-06-20T17:49:22.887 に答える
154

以下のコメント投稿者が正しく指摘しているように、これはサービスの一般的なソリューションではなく、アクティビティから起動されたスレッドのみを対象としています(サービスはそのようなスレッドである可能性がありますが、すべてがそうであるとは限りません)。サービスとアクティビティのコミュニケーションの複雑なトピックについては、公式ドキュメントのサービスセクション全体をお読みください。複雑なので、基本を理解することをお勧めします: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() {
});

Doc:http ://developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29

これがあなたが探しているものであることを願っています。

于 2012-06-20T22:19:47.087 に答える
63

Kotlinバージョン

アクティビティをしているときは、

runOnUiThread {
    //code that runs in main
}

アクティビティコンテキストがある場合、mContextは次に使用します

mContext.runOnUiThread {
    //code that runs in main
}

コンテキストが利用できない場所にいる場合は、

Handler(Looper.getMainLooper()).post {  
    //code that runs in main
}
于 2019-07-02T12:14:03.843 に答える
32

コンテキストへのアクセス権がない場合は、別の簡単な方法があります。

1)。メインルーパーからハンドラーを作成します。

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

2)。Runnableインターフェイスを実装します。

Runnable runnable = new Runnable() { // your code here }

3)。RunnableをuiHandlerに投稿します。

uiHandler.post(runnable);

以上です;-)スレッドを楽しんでください。ただし、スレッドを同期することを忘れないでください。

于 2015-07-03T07:15:47.033 に答える
29

スレッドでコードを実行する場合、たとえば、アクションを遅らせる場合はrunOnUiThread、コンテキストから呼び出す必要があります。たとえば、コードがMainActivityクラス内にある場合は、次を使用します。

MainActivity.this.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        myAction();
    }
});

メソッドをメイン(UIスレッド)または他のスレッドから呼び出すことができる場合は、次のようなチェックが必要です。

public void myMethod() {
   if( Looper.myLooper() == Looper.getMainLooper() ) {
       myAction();
   }
   else {

}
于 2013-09-27T09:27:29.960 に答える
27

要約されたコードブロックは次のとおりです。

   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
    })
于 2018-02-20T17:46:10.150 に答える
5

特にコンテキストがない場合、RxAndroidを使用している場合、最も簡単な方法は次のようになります。

AndroidSchedulers.mainThread().scheduleDirect {
    runCodeHere()
}
于 2018-10-30T03:54:01.370 に答える
5

ハンドラーを使用したより正確なKotlinコード:

Handler(Looper.getMainLooper()).post {  
 // your codes here run on main Thread
 }
于 2019-01-14T11:04:17.300 に答える
4

私が考えることができる1つの方法はこれです:

1)UIをサービスにバインドします。
2)以下のようなメソッドを公開しBinderますHandler

public void registerHandler(Handler handler) {
    mHandler = handler;
}

3)UIスレッドで、サービスにバインドした後、上記のメソッドを呼び出します。

mBinder.registerHandler(new Handler());

4)サービスのスレッドのハンドラーを使用して、タスクを投稿します。

mHandler.post(runnable);
于 2012-06-20T16:41:01.240 に答える
4

HandlerThreadAndroidの通常のJavaスレッドよりも優れたオプションです。

  1. HandlerThreadを作成して開始します
  2. HandlerThreadからLooperを使用してハンドラーを作成します。requestHandler
  3. post上のRunnableタスクrequestHandler

からのUIスレッドとの通信HandlerThread

  1. メインスレッド のHandlerwithを作成します:そしてoverrideメソッドLooperresponseHandlerhandleMessage
  2. Runnable他のスレッド(HandlerThreadこの場合)のタスク内で、呼び出しsendMessageますresponseHandler
  3. このsendMessage結果、inが呼び出さhandleMessageresponseHandlerます。
  4. から属性を取得して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

android-looper-handler-handlerthread-i

于 2017-05-09T12:40:10.967 に答える
4

これは古い質問ですが、KotlinとJavaの両方で使用しているメインスレッドのワンライナーに出くわしました。これはサービスにとって最善の解決策ではないかもしれませんが、フラグメント内のUIを変更する何かを呼び出す場合、これは非常に単純で明白です。

Java(8):

 getActivity().runOnUiThread(()->{
      //your main thread code
 });

Kotlin:

this.runOnUiThread {
     //your main thread code
}
于 2018-06-14T22:05:26.857 に答える
4

したがって、最も便利なのは、次のようなことを行うことです。

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)}
}
于 2019-10-21T09:51:40.663 に答える
2
ContextCompat.getMainExecutor(context).execute {
  // do something
}
于 2021-09-13T08:18:25.740 に答える
1

この方法に従ってください。この方法を使用すると、バックグラウンドスレッドから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);
    }
于 2018-02-19T13:42:53.833 に答える
1

Kotlinの場合、Anko corountinesを使用できます:

アップデート

doAsync {
   ...
}

非推奨

async(UI) {
    // Code run on UI thread
    // Use ref() instead of this@MyActivity
}
于 2018-09-17T08:00:49.903 に答える
0
public void mainWork() {
    new Handler(Looper.getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            //Add Your Code Here
        }
    });
}

これは、サービスクラスでも問題なく機能します。

于 2018-08-23T12:24:21.853 に答える
-1

Kotlinを使用すると、関数内では次のようになります。

runOnUiThread {
   // Do work..
}
于 2019-09-25T09:40:09.827 に答える