在android服务中,我创建了一些用于执行某些后台任务的线程。
我遇到线程需要在主线程的消息队列上发布某个任务的情况,例如Runnable
。
有没有办法获取主线程的Handler
并从我的其他帖子发布Message
/ Runnable
?
谢谢,
答案 0 :(得分:560)
注意:这个答案引起了很多关注,我需要更新它。自从原始答案发布以来,@ dzeikei的评论几乎与原始答案一样受到关注。所以这里有两种可能的解决方案:
<强> 1。如果您的后台主题引用了Context
对象:
确保后台工作线程有权访问Context对象(可以是Application上下文或Service上下文)。然后在后台工作线程中执行此操作:
// 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);
答案 1 :(得分:129)
正如下面的评论者所指出的,这不是服务的一般解决方案,仅适用于从您的活动启动的线程(服务可以是这样的线程,但不是所有这些线程)。 关于服务活动沟通的复杂话题,请阅读官方文档的整个服务部分 - 这很复杂,因此理解基础知识是值得的: 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() {
});
希望这就是你要找的东西。
答案 2 :(得分:28)
如果您无法访问上下文,还有另一种简单的方法。
1)。从主循环器创建一个处理程序:
Handler uiHandler = new Handler(Looper.getMainLooper());
2)。实现Runnable接口:
Runnable runnable = new Runnable() { // your code here }
3)。将Runnable发布到uiHandler:
uiHandler.post(runnable);
全部;-)享受线程乐趣,但不要忘记同步它们。
答案 3 :(得分:27)
如果您在线程中运行代码,例如延迟一些动作,然后你需要从上下文中调用runOnUiThread
。例如,如果您的代码在MainActivity
类中,请使用:
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
myAction();
}
});
如果您的方法可以从main(UI线程)或其他线程调用,则需要检查:
public void myMethod() {
if( Looper.myLooper() == Looper.getMainLooper() ) {
myAction();
}
else {
}
答案 4 :(得分:16)
精简代码块如下:
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
// things to do on the main thread
}
});
这不涉及传递Activity引用或Application引用。
Kotlin等效:
Handler(Looper.getMainLooper()).post(Runnable {
// things to do on the main thread
})
答案 5 :(得分:4)
我能想到的一个方法是:
1)让UI绑定到服务
2)通过注册Binder
的{{1}}公开类似下面的方法:
Handler
3)在UI线程中,绑定到服务后调用上面的方法:
public void registerHandler(Handler handler) {
mHandler = handler;
}
4)使用服务主题中的处理程序发布您的任务:
mBinder.registerHandler(new Handler());
答案 6 :(得分:4)
最简单的方法,尤其是在没有上下文的情况下,如果您使用的是RxAndroid,则可以执行以下操作:
AndroidSchedulers.mainThread().scheduleDirect {
runCodeHere()
}
答案 7 :(得分:2)
HandlerThread
是Android中普通java线程的更好选择。
requestHandler
post
Runnable
上的requestHandler
任务
醇>
与来自HandlerThread
Handler
创建Looper
responseHandler
并覆盖handleMessage
方法Runnable
内部任务(本例中为HandlerThread
),在sendMessage
上致电responseHandler
sendMessage
handleMessage
responseHandler
Message
次TextView
次结果调用。{/ 1}
HandlerThread
获取属性并对其进行处理,更新用户界面 示例:使用从Web服务收到的数据更新Handler
。由于应在非UI线程上调用Web服务,因此为网络操作创建了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);
。从Web服务获取内容后,将消息发送到主线程(UI线程)处理程序,Array=[ "10", "1", "101", "NA", "100", "20", "210", "200", "NA", "7" ]
将处理消息并更新UI。
示例代码:
Sorted=[ "1", "7", "10", "20", "100", "101", "200", "210", "NA", "NA" ]
有用的文章:
handlerthreads-and-why-you-should-be-using-them-in-your-android-apps
答案 8 :(得分:2)
我知道这是一个老问题,但我遇到了一个我在Kotlin和Java中使用的主线程单线程。这可能不是服务的最佳解决方案,但是为了调用会改变片段内部UI的内容,这非常简单明了。
Java(8):
getActivity().runOnUiThread(()->{
//your main thread code
});
科特林:
this.runOnUiThread {
//your main thread code
}
答案 9 :(得分:2)
使用处理程序的更精确的Kotlin代码:
Handler(Looper.getMainLooper()).post {
// your codes here run on main Thread
}
答案 10 :(得分:1)
遵循此方法。使用这种方式,您只需从后台线程更新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);
}
答案 11 :(得分:1)
所以最方便的是执行以下操作:
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)}
}
答案 12 :(得分:0)
public void mainWork() {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
//Add Your Code Here
}
});
}
这也可以在服务类中正常工作。
答案 13 :(得分:0)
对于Kotlin,您可以使用Anko corountines:
更新
doAsync {
...
}
已弃用
async(UI) {
// Code run on UI thread
// Use ref() instead of this@MyActivity
}
答案 14 :(得分:0)
您正在参加活动时,请使用
runOnUiThread {
//code that runs in main
}
您具有活动上下文时,然后使用mContext
mContext.runOnUiThread {
//code that runs in main
}
当您位于没有可用上下文的地方时,请使用
Handler(Looper.getMainLooper()).post {
//code that runs in main
}
答案 15 :(得分:-1)
对于Kotlin,它在任何函数中都是这样的:
runOnUiThread {
// Do work..
}