在一个android服务,我已经创建线程(s)做一些后台任务。

我有一个线程需要在主线程的消息队列上发布某个任务的情况,例如一个可运行的。

有没有办法得到主线程的处理程序和post Message/Runnable到它从我的其他线程?


当前回答

注意:这个答案已经得到了如此多的关注,我需要更新它。自从原来的答案被发布后,@dzeikei的评论获得了几乎和原来答案一样多的关注。这里有两种可能的解决方案:

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);

其他回答

最简单的方法,特别是如果你没有context,如果你在使用RxAndroid,你可以这样做:

AndroidSchedulers.mainThread().scheduleDirect {
    runCodeHere()
}

压缩代码块如下所示:

   new Handler(Looper.getMainLooper()).post(new Runnable() {
       @Override
       public void run() {
           // things to do on the main thread
       }
   });

这并不涉及传递活动引用或应用程序引用。

芬兰湾的科特林相当于:

    Handler(Looper.getMainLooper()).post(Runnable {
        // things to do on the main thread
    })

遵循这个方法。使用这种方法,您可以简单地从后台线程更新UI。runOnUiThread工作在主(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);
    }
ContextCompat.getMainExecutor(context).execute {
  // do something
}

所以最方便的方法是:

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)}
}