转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中的一些问题,可能有理解错的地方,请大大们指出来。

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

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

  1. Handler实现线程间的通信2

    与Handler实现线程间的通信1反过来MainThread中向WorkerThread中发送消息

  2. Handler实现线程间的通信1

    通过Handler实现线程间的通信,在主线程当中实现Handler的handlerMessage()方法,在WorkerThread中通过Handler发送消息 Handler实现线程间的通信实例: ...

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

    现在用一个实例来演示一下自己的新建线程与UI线程间的通信. UI界面包含3个控件: 一个输入框,用来输入数字: 一个显示框,用来显示从2开始,到输入数字之间的所有质数: 一个按钮,点击后获取输入框输入 ...

  4. android 线程间的通信

    (转自:http://www.cnblogs.com/allin/archive/2010/05/19/1738800.html) andriod提供了 Handler 和 Looper 来满足线程间 ...

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

    keyword:Android 使用handler实现线程间发送消息 (主线程 与 子线程之间).(子线程 与 子线程之间) 相信大家平时都有使用到异步线程往主线程(UI线程)发送消息的情况. 本文主 ...

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

    iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任 ...

  7. Java核心知识点学习----多线程并发之线程间的通信,notify,wait

    1.需求: 子线程循环10次,主线程循环100次,这样间隔循环50次. 2.实现: package com.amos.concurrent; /** * @ClassName: ThreadSynch ...

  8. java多线程详解(6)-线程间的通信wait及notify方法

    Java多线程间的通信 本文提纲 一. 线程的几种状态 二. 线程间的相互作用 三.实例代码分析 一. 线程的几种状态 线程有四种状态,任何一个线程肯定处于这四种状态中的一种:(1). 产生(New) ...

  9. iOS边练边学--多线程NSOperation介绍,子类实现多线程的介绍(任务和队列),队列的取消、暂停(挂起)和恢复,操作依赖与线程间的通信

    一.NSOperation NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation对象中 然后将NSOperation对象添加 ...

随机推荐

  1. js调用.net后台

    <head runat=server> <script type="text/javascript"> $(function () { var js_tim ...

  2. PHP 字符串处理 总结

    PHP 字符串处理 PHP 字符串处理 PHP 的字符串处理功能非常强大,主要包括: 字符串输出 echo():输出一个或多个字符串 print():输出一个字符串 printf():输出格式化字符串 ...

  3. drawInRect:withAttributes:

    - (void)drawRect:(CGRect)frame { NSMutableParagraphStyle *textStyle = [[NSMutableParagraphStyle defa ...

  4. Log4J logger图片

  5. BZOJ 3196

    program bzoj3196; ; maxn=; maxm=; var n,m,time,temp:longint; root,a:..maxn] of longint; left,right,r ...

  6. hdu 4730 We Love MOE Girls

    http://acm.hdu.edu.cn/showproblem.php?pid=4730 直接用string类处理字符串. AC代码: #include<iostream> #incl ...

  7. Hive实现oracle的Minus函数

    在Oracle中minus运算的主要功能是: 在进行两个表格或者两个查询结果的时候,返回在第一个表格/查询结果中与第二个表格/查询结果不同样的记录. 结果不同样的记录包括两种情况:A,B 表中某一行的 ...

  8. 多线程wait()和sleep()以及InterruptedException异常

    1.核心区别: sleep用于线程控制,wait用于线程间的通信. sleep是Thread类的方法,是让线程休息一段时间,然后自动恢复运行,与其他线程无关,与同步无关,也与锁无关(拿锁时不会释放锁) ...

  9. 二分法查找的C语言实现:

    #include <stdio.h> int binSearch(int, int, int); main() { int i, n = 10, x = 7; //这里假设把数组a[]定义 ...

  10. iOS UILabel 使用姿势大全(标红关键字)

    一.初始化 ? 1 2 3 UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(40, 40, 120, 44)];       ...