Handler、Looper和MessageQueue的基本原理
来源:互联网 发布:淘宝一件代发好做吗 编辑:程序博客网 时间:2024/06/05 10:46
为什么线程不能直接通信
Android提供了Handler和Looper来进行线程间的通信,那么首先我们需要明白,线程间为什么不能直接通信,而需要借助Handler-Looper机制来完成。
一个应用程序的多个线程分为主线程(MainThread)和其它线程(WorkerThread)。MainThread主要负责接收用户的输入以及将运算结果反馈给用户,同时负责对UI的操作,而整个运算过程都是交给WorkerThread来处理的,因为在运算的过程中很可能会造成线程阻塞,为了保证主线程不会阻塞,一定要将可能会造成阻塞的操作放到WorkerThread中。而且在WorkerThread中也不能直接对UI进行操作,所以必须在主线程和其它线程之间建立一种机制来满足它们之间的通信,这种机制就是Handler-Looper机制。
什么是Handler、Looper以及MessageQueue
从上面这张图我们可以看出,Handler的作用是将消息push进消息队列中,而Looper将消息从队列中取出,再送到Handler处让Handler对消息进行处理。如果不清楚原理,看到这肯定已经懵逼了…为什么Handler将消息发出去最后又要回到Handler呢?那么接下来我们将来探讨这个问题。
不过在这之前呢,我们需要明白,Android所有UI相关的代码都是运行在主线程(MainThread)中的,在一个WorkerThread中是无法直接对UI(ProgressBar例外)进行操作的
WorkerThread到MainThread的通信
在WorkerThread中调用Handle的sendMessage() 方法将消息发送到消息队列中,然后Looper会将消息从队列中取出,调用与该消息对应的Handler(位于主线程中)的handlerMessage()方法将消息传送给Handler。具体实现代码如下
public class MainActivity extends ActionBarActivity { private TextView textView; private Button button; private Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView)findViewById(R.id.textViewId); button = (Button)findViewById(R.id.buttonId); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Thread t = new WorkerThread(); t.start(); } }); handler = new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub String s = (String)msg.obj; textView.setText(s); } }; } class WorkerThread extends Thread{ @Override public void run() { // TODO Auto-generated method stub try { Thread.sleep(2*1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } String s = "网络返回数据"; Message msg = handler.obtainMessage(); msg.obj = s; handler.sendMessage(msg); } }
MainThread到WorkerThread的通信
在WorkerThread中创建Handler对象,同时Looper通过Looper.loop()方法不断循环接收消息,接受到之后,调用与该消息对应的handler的handlerMessage()方法处理消息(如果消息队列中没有消息对象,则线程阻塞),而在Mainthread的button监听器中通过handler.sendMessage()方法将消息送至消息队列中。具体代码实现如下:
public class MainActivity extends ActionBarActivity { private Button button; private Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button)findViewById(R.id.buttonId); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Message msg = handler.obtainMessage(); handler.sendMessage(msg); } }); WorkerThread wt = new WorkerThread(); wt.start(); } class WorkerThread extends Thread{ @Override public void run() { // TODO Auto-generated method stub Looper.prepare(); handler = new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub System.out.println("消息已收到"); } }; Looper.loop(); } }
从上面的代码可以看出,MainThread和workerThread之间正是利用了消息从Handler到Looper再到Handler这样的机制巧妙的解决了在WorkerThread中不能访问位于MainThread中的UI控件的问题。
同时还必须了解Handler在创建消息、发送消息和处理消息时的原理,以下来自
http://blog.csdn.net/ZBJDSBJ/article/details/38795871
1.Handler创建消息
每一个消息都需要被指定的Handler处理,通过Handler创建消息便可以完成此功能。Android消息机制中引入了消息池。Handler创建消息时首先查询消息池中是否有消息存在,如果有直接从消息池中取得,如果没有则重新初始化一个消息实例。使用消息池的好处是:消息不被使用时,并不作为垃圾回收,而是放入消息池,可供下次Handler创建消息时使用。消息池提高了消息对象的复用,减少系统垃圾回收的次数。消息的创建流程如图所示。
2.Handler发送消息
UI主线程初始化第一个Handler时会通过ThreadLocal创建一个Looper,该Looper与UI主线程一一对应。使用ThreadLocal的目的是保证每一个线程只创建唯一一个Looper。之后其他Handler初始化的时候直接获取第一个Handler创建的Looper。Looper初始化的时候会创建一个消息队列MessageQueue。至此,主线程、消息循环、消息队列之间的关系是1:1:1。
Handler、Looper、MessageQueue的初始化流程如图所示:
Hander持有对UI主线程消息队列MessageQueue和消息循环Looper的引用,子线程可以通过Handler将消息发送到UI线程的消息队列MessageQueue中。
3.Handler处理消息
UI主线程通过Looper循环查询消息队列UI_MQ,当发现有消息存在时会将消息从消息队列中取出。首先分析消息,通过消息的参数判断该消息对应的Handler,然后将消息分发到指定的Handler进行处理。
- Handler、Looper和MessageQueue的基本原理
- handler looper和messageQueue
- Handler、Looper和MessageQueue
- Handler、Looper和MessageQueue
- Looper, messageQueue和Handler的关系
- Handler、Looper和MessageQueue的关系
- Message,Handler,MessageQueue和Looper
- Handler,Looper,MessageQueue的实现
- Handler、MessageQueue 、Looper的关系
- Handler Looper MessageQueue的应用
- Handler Looper MessageQueue 的关系
- 线程 (Handler、Looper、MessageQueue和Thread的理解)
- Android中的Handler, Looper, MessageQueue和Thread的关系
- 简析Handler、Looper和MessageQueue三者的关系
- Message MessageQueue Runnable Looper 和Handler的关系理解
- Android中的Handler、Looper和MessageQueue的使用以及原理
- Handler,looper,MessageQueue及 handlerThread 之间的关联和用法
- Handler,Looper ,Message和MessageQueue 之间的关系
- House Robber III
- 第二十课 查找的艺术 【项目1-4】
- android学习 读书笔记之 android 绘图shape
- 卡尔曼滤波器(THE KALMAN FILTER)的数学原理
- JS关键字详解
- Handler、Looper和MessageQueue的基本原理
- python web框架企业实战详解(第六期)\第三课时-css&bootstrap
- 详解JS中的Object对象
- 远程桌面不能拷贝文件的问题
- Phantomjs+Nodejs+Mysql数据抓取(1.数据抓取)
- 创新来自哪里?
- 自定义和隐藏(自定义TabBar)
- android四大组件(详细总结)
- JavaIO流个人总结,Much Demo