本文翻译自:Running code in main thread from another thread
In an android service I have created thread(s) for doing some background task. 在android服务中,我创建了用于执行某些后台任务的线程。
I have a situation where a thread needs to post certain task on main thread's message queue, for example a Runnable
. 我遇到一种情况,线程需要在主线程的消息队列上发布某些任务,例如Runnable
。
Is there a way to get Handler
of the main thread and post Message
/ Runnable
to it from my other thread ? 有没有办法获取主线程的Handler
并从其他线程向其发布Message
/ Runnable
?
Thanks, 谢谢,
#1楼
参考:https://stackoom.com/question/kflF/从另一个线程在主线程中运行代码
#2楼
One method I can think of is this: 我能想到的一种方法是:
1) Let the UI bind to the service. 1)让UI绑定到服务。
2) Expose a method like the one below by the Binder
that registers your Handler
: 2)通过注册您的Handler
的Binder
公开以下方法:
public void registerHandler(Handler handler) {
mHandler = handler;
}
3) In the UI thread, call the above method after binding to the service: 3)在UI线程中,绑定到服务后调用上述方法:
mBinder.registerHandler(new Handler());
4) Use the handler in the Service's thread to post your task: 4)使用服务线程中的处理程序来发布您的任务:
mHandler.post(runnable);
#3楼
NOTE: This answer has gotten so much attention, that I need to update it. 注意:此答案已引起广泛关注,我需要对其进行更新。 Since the original answer was posted, the comment from @dzeikei has gotten almost as much attention as the original answer. 自从原始答案发布以来,@ dzeikei的评论几乎和原始答案一样受到关注。 So here are 2 possible solutions: 因此,这里有两种可能的解决方案:
1. If your background thread has a reference to a Context
object: 1.如果您的后台线程引用了Context
对象:
Make sure that your background worker threads have access to a Context object (can be the Application context or the Service context). 确保您的后台工作线程可以访问Context对象(可以是Application上下文或Service上下文)。 Then just do this in the background worker thread: 然后只需在后台工作线程中执行此操作:
// 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. If your background thread does not have (or need) a Context
object 2.如果您的后台线程没有(或不需要) Context
对象
(suggested by @dzeikei): (由@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);
#4楼
As a commenter below pointed correctly, this is not a general solution for services, only for threads launched from your activity (a service can be such a thread, but not all of those are). 正如下面的评论者正确指出的那样,这不是针对服务的通用解决方案,仅适用于从您的活动启动的线程(服务可以是这样的线程,但并非所有都是这样的)。 On the complicated topic of service-activity communication please read the whole Services section of the official doc - it is complex, so it would pay to understand the basics: http://developer.android.com/guide/components/services.html#Notifications 关于服务活动通信的复杂主题,请阅读官方文档的整个“服务”部分-它很复杂,因此有必要了解基本知识: http : //developer.android.com/guide/components/services.html #通知
The method below may work in simpliest cases. 下面的方法可能在最简单的情况下起作用。
If I understand you correctly you need some code to be executed in GUI thread of the application (cannot think about anything else called "main" thread). 如果我对您的理解正确,那么您需要在应用程序的GUI线程中执行一些代码(不能考虑其他称为“主”线程的代码)。 For this there is a method on Activity
: 为此,在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 Doc: http : //developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29
Hope this is what you are looking for. 希望这是您想要的。
#5楼
If you run code in a thread, eg do delaying some action, then you need to invoke runOnUiThread
from the context. 如果您在线程中运行代码(例如,延迟某些操作),则需要从上下文中调用runOnUiThread
。 For example, if your code is inside MainActivity
class then use this: 例如,如果您的代码在MainActivity
类中,则使用以下代码:
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
myAction();
}
});
If your method can be invoked either from main (UI thread) or from other threads you need a check like: 如果您的方法可以从主线程(UI线程)或从其他线程调用,则需要进行如下检查:
public void myMethod() {
if( Looper.myLooper() == Looper.getMainLooper() ) {
myAction();
}
else {
}
#6楼
There is another simple way, if you don't have an access to the Context. 如果您无权访问上下文,则有另一种简单的方法。
1). 1)。 Create a handler from the main looper: 从主循环器创建一个处理程序:
Handler uiHandler = new Handler(Looper.getMainLooper());
2). 2)。 Implement a Runnable interface: 实现一个Runnable接口:
Runnable runnable = new Runnable() { // your code here }
3). 3)。 Post your Runnable to the uiHandler: 将您的Runnable发布到uiHandler:
uiHandler.post(runnable);
That's all ;-) Have fun with threads, but don't forget to synchronize them. 仅此而已;-)玩弄线程,但不要忘记同步它们。