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

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

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


当前回答

还有另一种简单的方法,如果你没有访问Context的权限。

1).从主循环程序创建一个处理程序:

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

2).实现一个可运行的接口:

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

3).发布你的Runnable到uiHandler:

uiHandler.post(runnable);

这就是全部;-)享受线程的乐趣,但不要忘记同步它们。

其他回答

我能想到的一个方法是:

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

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

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

mBinder.registerHandler(new Handler());

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

mHandler.post(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);

压缩代码块如下所示:

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

如果你在线程中运行代码,例如延迟一些动作,那么你需要从上下文调用runOnUiThread。例如,如果你的代码在MainActivity类中,那么使用这个:

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

如果你的方法可以从main (UI线程)或其他线程调用,你需要像这样检查:

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

}

遵循这个方法。使用这种方法,您可以简单地从后台线程更新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);
    }