Android应用开发——线程间通信之Handler+Looper+MessageQueue
2014-04-12 18:34
776 查看
1、需求
每个Android应用程序都运行在一个dalvik虚拟机进程中,进程开始的时候会启动一个主线程(MainThread),主线程负责处理和ui相关的事件,因此主线程通常又叫UI线程。而由于Android采用UI单线程模型(线程不安全),所以只能在主线程中对UI元素进行操作。如果在非UI线程直接对UI进行了操作,则会报错。
为了解决以上问题,Android中提供了Handler+Looper+MessageQueue的消息循环机制。可以利用这个机制来实现线程间的通信。那么,我们就可以在非UI线程发送消息到UI线程,最终让Ui线程来进行ui的操作。对于运算量较大的操作和IO操作,我们需要新开线程来处理这些繁重的工作,以免阻塞ui线程。
2、Handler+Looper+MessageQueue原理
Android使用消息机制实现线程间的通信,线程通过Looper建立自己的消息循环,MessageQueue是FIFO的消息队列,Looper负责从MessageQueue中取出消息,并且分发到消息指定目标Handler对象。Handler对象绑定到线程的局部变量Looper,封装了发送消息和处理消息的接口。
消息循环的核心是Looper,Looper持有消息队列MessageQueue对象,一个线程可以把Looper设为该线程的局部变量,这就相当于这个线程建立了一个对应的消息队列。Handler的作用就是封装发送消息和处理消息的过程,让其他线程只需要操作Handler就可以发消息给创建Handler的线程。
为一个线程建立消息循环有四个步骤:
1、 初始化Looper
2、 绑定handler到线程实例的Looper对象
3、 定义处理消息的方法
4、 启动消息循环
3、实例
3.1 UI线程发送消息至Work Thread
3.1.1 初始化Looper
一个线程在调用Looper的静态方法prepare()时,这个线程会新建一个Looper对象,并放入到线程的局部变量中,而这个变量是不和其他线程共享的。
prepare方法源代码如下:
Looper中定义了成员变量,即该线程对象拥有了该Looper对象,相当于工作线程拥有了自己的消息队列。
3.1.2 绑定handler到线程实例的Looper对象
该变量必须定义在UI线程和Work线程都能访问的地方:
但是,创建Handler对象时,必须在Work线程中,这样才能将Handler绑定到Work线程实例的Looper对象:
Handler类的构造函数如下:
Handler通过mLooper = Looper.myLooper();绑定到线程的局部变量Looper上去,同时Handler通过mQueue =mLooper.mQueue;获得线程的消息队列。此时,Handler就绑定到创建此Handler对象的线程的消息队列上了。
3.1.3 定义处理消息的方法
3.1.4 启动消息循环
3.2 Work Thread发送消息至UI线程
参考:
/article/7601755.html 比较详细
/article/7601759.html
/article/1645877.html
http://www.eoeandroid.com/thread-40479-1-1.html
关于obtainMessage和sendMessage方法:
/article/6997010.html 比较详细
/article/9168267.html
每个Android应用程序都运行在一个dalvik虚拟机进程中,进程开始的时候会启动一个主线程(MainThread),主线程负责处理和ui相关的事件,因此主线程通常又叫UI线程。而由于Android采用UI单线程模型(线程不安全),所以只能在主线程中对UI元素进行操作。如果在非UI线程直接对UI进行了操作,则会报错。
为了解决以上问题,Android中提供了Handler+Looper+MessageQueue的消息循环机制。可以利用这个机制来实现线程间的通信。那么,我们就可以在非UI线程发送消息到UI线程,最终让Ui线程来进行ui的操作。对于运算量较大的操作和IO操作,我们需要新开线程来处理这些繁重的工作,以免阻塞ui线程。
2、Handler+Looper+MessageQueue原理
Android使用消息机制实现线程间的通信,线程通过Looper建立自己的消息循环,MessageQueue是FIFO的消息队列,Looper负责从MessageQueue中取出消息,并且分发到消息指定目标Handler对象。Handler对象绑定到线程的局部变量Looper,封装了发送消息和处理消息的接口。
消息循环的核心是Looper,Looper持有消息队列MessageQueue对象,一个线程可以把Looper设为该线程的局部变量,这就相当于这个线程建立了一个对应的消息队列。Handler的作用就是封装发送消息和处理消息的过程,让其他线程只需要操作Handler就可以发消息给创建Handler的线程。
为一个线程建立消息循环有四个步骤:
1、 初始化Looper
2、 绑定handler到线程实例的Looper对象
3、 定义处理消息的方法
4、 启动消息循环
3、实例
3.1 UI线程发送消息至Work Thread
3.1.1 初始化Looper
一个线程在调用Looper的静态方法prepare()时,这个线程会新建一个Looper对象,并放入到线程的局部变量中,而这个变量是不和其他线程共享的。
/* 定义工作线程类 */ class WorkThread extends Thread{ /* 重写run方法 */ public void run(){ /* Looper初始化 */ Looper.prepare(); } }
prepare方法源代码如下:
private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
Looper中定义了成员变量,即该线程对象拥有了该Looper对象,相当于工作线程拥有了自己的消息队列。
final MessageQueue mQueue;
3.1.2 绑定handler到线程实例的Looper对象
该变量必须定义在UI线程和Work线程都能访问的地方:
private Handler myHandler;
但是,创建Handler对象时,必须在Work线程中,这样才能将Handler绑定到Work线程实例的Looper对象:
/* 定义工作线程类 */ class WorkThread extends Thread{ /* 重写run方法 */ public void run(){ /* Looper初始化 */ Looper.prepare(); /* 创建myHandler对象 */ myHandler = new Handler(){ }; } }
Handler类的构造函数如下:
public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } mLooper = Looper.myLooper(); /* 绑定Looper对象 */ if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; /* 绑定消息队列 */ mCallback = callback; mAsynchronous = async; }
Handler通过mLooper = Looper.myLooper();绑定到线程的局部变量Looper上去,同时Handler通过mQueue =mLooper.mQueue;获得线程的消息队列。此时,Handler就绑定到创建此Handler对象的线程的消息队列上了。
3.1.3 定义处理消息的方法
/* 创建myHandler对象 */ myHandler = new Handler(){ public void handleMessage(Message msg) { } };
3.1.4 启动消息循环
Looper.loop();
3.2 Work Thread发送消息至UI线程
参考:
/article/7601755.html 比较详细
/article/7601759.html
/article/1645877.html
http://www.eoeandroid.com/thread-40479-1-1.html
关于obtainMessage和sendMessage方法:
/article/6997010.html 比较详细
/article/9168267.html
相关文章推荐
- Android--Handler+Looper+MessageQueue+Thread线程之间的通信
- Android:Handler+Looper+MessageQueue+Thread(线程间的通信)随记
- Android开发之单线程模型中Message、Handler、MessageQueue、Looper之间的关系
- Android应用开发多线程基础之Handler,Looper,Message,MessageQueue,Runnable之间的关系
- Android开发之漫漫长途 VII——Android消息机制(Looper Handler MessageQueue Message)
- Android异步消息处理线程之----Looper+MessageQueue+Handler
- Android开发之多线程 ——Handler message messageQueue Looper
- Android开发: 线程间消息通信 Looper 和Handler
- Android开发: 线程间消息通信 Looper 和Handler
- android多线程开发线程池(Handler+Thread+Message(queue)+Cache)应用
- Android 线程4件套 MessageQueue Message Looper Handler之Looper
- Android线程间通信机制——深入理解 Looper、Handler、Message
- Android异步消息处理 Handler Looper MessageQueue
- 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
- Android Handler Looper MessageQueue原理分析
- Android异步处理三:Handler+Looper+MessageQueue深入详解
- Android异步处理三:Handler+Looper+MessageQueue深入详解
- android编程之在单线程模型中Message、Handler、Message Queue、Looper之间的关系
- Thread和Looper以及Handler和Message详解 Android开发必读
- android UI更新问题 Thread和Looper以及Handler和Message详解 Android开发必读