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

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

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


当前回答

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

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

其他回答

我能想到的一个方法是:

1)让UI绑定到服务。 2)暴露一个方法,就像下面一个由Binder注册你的处理程序:

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

3)在UI线程中,绑定到服务后调用上述方法:

mBinder.registerHandler(new Handler());

4)使用服务线程中的处理程序来发布你的任务:

mHandler.post(runnable);

我知道这是一个老问题,但我遇到了一个在Kotlin和Java中都使用的主线程一行程序。对于服务来说,这可能不是最好的解决方案,但对于调用将改变片段内UI的东西来说,这是非常简单和明显的。

Java (8):

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

科特林:

this.runOnUiThread {
     //your main thread code
}

注意:这个答案已经得到了如此多的关注,我需要更新它。自从原来的答案被发布后,@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);

正如下面一位评论者正确指出的那样,这不是服务的通用解决方案,只适用于从您的活动中启动的线程(服务可以是这样的线程,但不是所有线程都是)。 关于服务-活动通信这个复杂的话题,请阅读官方文档的整个服务部分——它很复杂,所以了解基本知识是有好处的: 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 % 28 java.lang.runnable % 29

希望这就是你要找的。

所以最方便的方法是:

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