Handler不同线程间的通信

转http://www.iteye.com/problems/69457

Activity启动后点击一个界面按钮后会开启一个服务(暂定为padService),在padService中会启动一个线程(暂定为Thread-3)发起Socket连接。我们项目中使用mina作为socket通信框架,用过mina的同志们应该熟悉,Thread-3只是负责监听,具体的消息处理是另外的线程。在我们的IoHandler中处理消息,现在的问题是,我需要在IoHander的sessionOpened方法中给Activity一个消息去更新UI界面,这个就涉及到不同线程间的通信了。

网上搜索后,在android中线程间通信使用Handler,Looper,Message这几个对象(不熟悉这些概念的同志们请自己查下)。

这是网上的一个使用例子:

Java代码

  1. public class Activity2 extends Activity implements OnClickListener{
  2. Button button = null;
  3. TextView text = null;
  4. MyHandler mHandler = null;
  5. Thread thread ;
  6. @Override
  7. protected void onCreate(Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.activity1);
  10. button = (Button)findViewById(R.id.btn);
  11. button.setOnClickListener(this);
  12. text = (TextView)findViewById(R.id.content);
  13. }
  14. public void onClick(View v) {
  15. switch (v.getId()) {
  16. case R.id.btn:
  17. thread = new MyThread();
  18. thread.start();
  19. break;
  20. }
  21. }
  22. private class MyHandler extends Handler{
  23. public MyHandler(Looper looper){
  24. super(looper);
  25. }
  26. @Override
  27. public void handleMessage(Message msg) {//处理消息
  28. text.setText(msg.obj.toString());
  29. }
  30. }
  31. private class MyThread extends Thread{
  32. @Override
  33. public void run() {
  34. Looper curLooper = Looper.myLooper();
  35. Looper mainLooper = Looper.getMainLooper();
  36. String msg ;
  37. if(curLooper==null){
  38. mHandler = new MyHandler(mainLooper);
  39. msg = "curLooper is null";
  40. }else{
  41. mHandler = new MyHandler(curLooper);
  42. msg = "This is curLooper";
  43. }
  44. mHandler.removeMessages(0);
  45. Message m = mHandler.obtainMessage(1, 1, 1, msg);
  46. mHandler.sendMessage(m);
  47. }
  48. }
  49. }

这个没有问题,基本上三个对象的使用也很清楚,myHandler虽然是由子线程new出来的,但主线程持有引用,在我们的项目中不能用,因为我们几个线程属于不同的类,我尝试用下面的方法解决:

在IoHandler中new一个android的handler,参数为主线程的Looper:

Java代码

  1. new Handler(Looper.getMainLooper()).sendMessage(msg);

IoHandler所在的线程给主线程发送消息(looper是主线程的,消息也就放在主线程的消息队列里了)

但是在主线程的handleMessage方法中得不到消息,尝试失败。

那么怎么办呢,让IoHandler持有主线程的handler引用,具体做法有两种方式:

1.  参数传递,把主线程的handler通过参数传递的形式传到IoHandler中。

2. 静态变量,把主线程的handler申明为公共静态变量

Java代码

  1. public static Handler mainHandler;

这样在Iohandler中使用

Java代码

  1. welcomeActivity.mainHandler.sendMessage(msg);

这两种方式在主线程的  handleMessage的方法中都可以得到IoHandler发送的消息。

本人使用的是静态变量解决的,因为有好几个来实现通信,参数传递太麻烦。

那为什么我的第一种尝试是失败的呢,我是把消息放到主线程的消息队列了啊,这就要看android的一些实现机制了。

通过网络和android的api,本人的理解如下:

Looper是MessageQueue和Handler沟通的桥梁,Handler通过Looper把消息放入消息队列(MessageQueue),你想把消息发给谁,就把谁的looper作为参数传给Handler

Java代码

  1. newHandler(Looper looper);

Looper把消息放入消息队列,并广播消息,这个不太好理解,我举例如下:

主线程的Handler我们这样定义:Handler mainHandler = new Handler();  如果Handler没有参数,默认为当前线程的Looper

子线程的Handler我们这样定义: Handler subHandler = newHandler(Looper.getMainLooper()); 参数为主线程的Looper

这样两个线程都会把消息放入主线程的消息队列里了。

现在mainHandler.sendMessage(), 消息进入主线程的消息队列,Looper广播消息,其实就是调用mainHandler的dispatchMessage方法,所有持有mianHandler引用的类都可以收到消息,注意啊,现在subHandler并不能接受到消息,因为Looper并没有调用subHandler的dispatchMessage方法,所以应该这样理解广播,A发送消息,那么A的Looper就调用A的dispatchMessage方法,别的B,C, D虽然也是A的Looper,但没有A的引用,所以B,C,D是接受不到消息的,如果B, C,D持有A的引用,但B,C,D不用A的Looper,那么也是接受不到消息的。这点在开发时要特别注意。

以上是我在使用Looper, Handler ,Message中的一些问题,可能有理解错的地方,请大大们指出来。

我的疑惑是难道子线程必须持有主线程的引用才可以给主线程发送消息吗?要知道我们的子线程并不一定和主线程一个类,可能在别的类中,这个引用传递实在太麻烦了,期望有更好的解决方式。

时间: 2024-11-16 20:06:20

Handler不同线程间的通信的相关文章

新建线程与UI线程间的通信

现在用一个实例来演示一下自己的新建线程与UI线程间的通信. UI界面包含3个控件: 一个输入框,用来输入数字: 一个显示框,用来显示从2开始,到输入数字之间的所有质数: 一个按钮,点击后获取输入框输入的数字,交给新建线程处理,线程计算质数后把结果传给UI线程,UI线程显示结果到显示框. XML如下: 1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android=&q

Android 使用handler实现线程间发送消息 (主线程 与 子线程之间)、(子线程 与 子线程之间)

keyword:Android 使用handler实现线程间发送消息 (主线程 与 子线程之间).(子线程 与 子线程之间) 相信大家平时都有使用到异步线程往主线程(UI线程)发送消息的情况. 本文主要研究Handler的消息发送. 包含主线程往子线程发送消息,子线程之间互相发送消息. 一.主线程向子线程发送消息. 实现过程比較简单: 主线程发送消息到异步线程.异步线程接收到消息后在再发送一条消息给主线程. 1. 初始化主线程的Handler,用来接收子线程的消息. 2. 启动异步线程.在异步线

线程间的通信、同步方式与进程间通信方式

1.线程间的通信方式 1)使用全局变量(由于多个线程可能更改全局变量,因此全局变量最好声明为volatile) 2) 使用消息实现通信 3)使用事件CEvent类实现线程间的通信 2.同步/异步(C端) 同步:在C端发出一个功能调用时,没有得到结果之前就不返回 异步: 一个请求通过事件触发后,得到服务器处理后才处理完毕 3. 阻塞/非阻塞(S端) 阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,cpu不会给线程分配时间片,即线程暂停运行).函数只有在得到

线程(二)__线程间的通信

线程间的通信:多个线程在处理同一资源,但是任务却不同.一.等待唤醒机制涉及的方法:1.wait();让线程处于冻结状态,被wait的线程会被存储到线程池中2.notify();唤醒线程池中的一个任意线程3.notifyAll();唤醒线程池中的所有线程这些方法都必须定义在同步中,因为这些方法是用于操作线程状态的方法,必须要明确到底操作的是哪个锁上的线程wait()对A锁上面的线程进行操作后只能用A锁的notify来唤醒.被wait之后的线程可认为放在线程池中. 为什么操作线程的方法wait no

VC++多线程编程-线程间的通信和线程同步

引用:http://blog.csdn.net/zjc0888/article/details/7372258 线程间通讯 一般而言,应用程序中的一个次要线程总是为主线程执行特定的任务,这样,主线程和次要线程间必定有一个信息传递的渠道,也就是主线程和次要线程间要进行通信.这种线程间的通信不但是难以避免的,而且在多线程编程中也是复杂和频繁的,下面将进行说明. 使用全局变量进行通信 由于属于同一个进程的各个线程共享操作系统分配该进程的资源,故解决线程间通信最简单的一种方法是使用全局变量.对于标准类型

网络开始---多线程---线程间的通信(掌握)(五)

1 #import "HMViewController.h" 2 3 @interface HMViewController () 4 @property (weak, nonatomic) IBOutlet UIImageView *imageView; 5 @end 6 7 @implementation HMViewController 8 9 - (void)viewDidLoad 10 { 11 [super viewDidLoad]; 12 // Do any additi

Java多线程之线程的状态以及线程间协作通信导致的状态变换

一:线程的状态以及变化图 Java中线程中状态可分为五种:New(新建状态),Runnable(就绪状态),Running(运行状态),Blocked(阻塞状态),Dead(死亡状态). New:新建状态,当线程创建完成时为新建状态,即new Thread(...),还没有调用start方法时,线程处于新建状态. Runnable:就绪状态,当调用线程的的start方法后,线程进入就绪状态,等待CPU资源.处于就绪状态的线程由Java运行时系统的线程调度程序(thread scheduler)来

iOS多线程技术—线程间的通信

iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任务后,转到另1个线程继续执行任务 线程间通信常用方法 - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; - (void)performSelector:(SE

iOS开发多线程篇—线程间的通信

iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任务后,转到另1个线程继续执行任务 线程间通信常用方法 - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; - (void)performSelector:(SE