转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. map的erase()释放内存

    STL中的map调用erase(it),当value值为指针时,释放内存: #include <iostream> #include <map> #include <st ...

  2. Java中常见的几种类型转换

    public class Main { public static void main(String[] args){ //Int型数字转换成字符串 int num1=123456; //方法1 St ...

  3. BZOJ 4260: Codechef REBXOR( trie )

    求出前缀和, 那么以第x个元素结尾的最大异或值是max(sumx^sump)(1≤p<x), 用trie加速. 后缀同理, 然后扫一遍就OK了.时间复杂度O(31N) ------------- ...

  4. C#调用C/C++动态库 封送结构体,结构体数组

    因为实验室图像处理的算法都是在OpenCV下写的,还有就是导航的算法也是用C++写的,然后界面部分要求在C#下写,所以不管是Socket通信,还是调用OpenCV的DLL模块,都设计到了C#和C++数 ...

  5. ViewFilpper

    package com.example.suneyaenews; import java.util.ArrayList; import java.util.HashMap; import java.u ...

  6. Binary Tree Preorder Traversal and Binary Tree Postorder Traversal

    Binary Tree Preorder Traversal Given a binary tree, return the preorder traversal of its nodes' valu ...

  7. werkzeug中reloader的实现

    在用flask开发时,如果把use_reloader设为True(debug设为True也能实现),那当你修改了app代码或调用环境发生改变时,服务器会自动重启,如下 * Detected chang ...

  8. django template出错

    解决方法一: 先导入settings >>> from django.conf import settings >>> settings.configure() & ...

  9. spring mvc实现ajax 分页

    使用到的技术: ·spring 3 mvc ·json ·jquery ·java ·mysql 首先,要了解如何在spring mvc中使用json. 以下主要从Dao和View及Controlle ...

  10. pythonxy 安装

    安装Numpy,发现错误: No module named msvccompiler in numpy.distutils; trying from distutils 目前python除了在 Win ...