在另一个线程的主线程中运行代码

在一个android服务中,我创build了一些线程来完成一些后台任务。

我有一个情况,线程需要在主线程的消息队列上发布特定的任务,例如一个Runnable

有没有办法获得主线程的Handler ,并从我的其他线程发布Message /运行到它?

谢谢,

注:这个答案已经得到如此多的关注,我需要更新它。 自从最初的回答发布以来,来自@dzeikei的评论几乎和最初的回答一样受到了关注。 所以这里有两个可能的解决scheme

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对象

(由@dzeikeibuild议):

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

正如下面的一个评论者所指出的那样,这不是一个通用的服务解决scheme,只有从你的活动发起的线程(一个服务可以是这样一个线程,但不是全部)。 关于服务活动沟通的复杂话题,请阅读官方文档的整个服务部分 – 这是复杂的,所以它将支付了解的基本知识: 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() { }); 

Doc: http : //developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29

希望这是你在找什么。

还有一个简单的方法,如果你没有访问上下文。

1)。 从主活套中创build一个处理程序:

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

2)。 实现一个Runnable接口:

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

3)。 将您的Runnable发布到uiHandler:

 uiHandler.post(runnable); 

这一切;-)与线程玩得开心,但不要忘记同步它们。

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

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

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

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

我能想到的一个方法是:

1)让UI绑定到服务。
2)由注册你的HandlerBinder公开下面的方法:

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

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

 mBinder.registerHandler(new Handler()); 

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

 mHandler.post(runnable); 

HandlerThread是Android中普通java线程的更好select。

  1. 创build一个HandlerThread并启动它
  2. 使用HandlerThread: requestHandler从Looper创build一个Handler
  3. requestHandlerpost一个Runnable任务

与来自HandlerThread UI线程进行通信

  1. 使用Looper为主线程创build一个HandlerresponseHandler并重写handleMessage方法
  2. 在其他线程(本例中为HandlerThread )的Runnable任务内,在responseHandler上调用sendMessage
  3. 这个sendMessage结果调用了handleMessage中的handleMessage
  4. Message获取属性并处理它,更新UI

示例 :使用从Web服务接收的数据更新TextView 。 由于Web服务应该在非UI线程上调用,因此为networking操作创build了HandlerThread 。 从Web服务获取内容后,将消息发送到主线程(UI线程)处理程序,该Handler程序将处理消息并更新UI。

示例代码:

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

有用的文章:

handlerthreads和-为什么-你-应该待使用了他们,在你的Android的应用程序

Android的尺蠖处理程序,handlerthread-I