1.前言
*定义*
1.一套Android消息传递机制/ 异步通信机制
2.主线程和子线程的通信媒介
*出现理由*
Android单线程更新更新UI机制
2.使用入门
第一种 : sendMessage(Message)

第二种: postMessage(Runnable)

示例 如下



两者的区别 :
1.发送消息到消息队列的方式不同 :
一个是直接Message对象,另一个是Runnable任务.
2.消息的处理位置不一样 :
一个是在某个地方发送消息,然后在Handler#handleMessage(Message)方法进行处理.
另一个是直接在Runnable#run()方法中直接处理.
应用 :
开发需求 : 下载图片,需要显示下载进度.
分 析 :
1.下载图片是耗时操作,所以,需要在子线程中进行.
2.更新进度,是UI操作,必须放在主线程中进行.
问 题 :
如何把子线程中的进度信息,在主线程进行显示?
方案之一 :
使用Handler,在主线程创建Handler对象,然后在图片下载的子线程回调中, 通过Handler把消息发送到主线程进行更新即可.
3.源码解析
1.类简介

2.流程分析
1.Looper.prepare();
对于UI线程,此过程已经在ActivityThread中进行
对于非UI线程需要手动调用,否则 3.#1中Bug就会出现
2.new Handler()
在Looper.myLooper()!=null 的线程中,创建一个Handler对象,进行消息的处理
3.Looper.loop()
遍历消息队列,发现消息即开始分发给同线程的Handler对象处理
3.Bug分析
#1. Can't create handler inside thread xxx that has not called Looper.prepare()
Bug代码
new Thread(new Runnable() {
@Override public void run() {
Handler handler = new Handler();
}
}).start();
#2.Only the original thread that created a view hierarchy can touch its views.
产生原因 : 在子线程更新UI
特例 : 在Activity # onCreate(Bundle)中可以在子线程更新UI,原因是ViewRootImpl # checkThread()是在Activity #onResume()时候创建!
#3.为什么Looper.loop()有一个死循环,但程序却并没有卡死?
1.Android是消息驱动的
2.Android程序的运行,就是一个个消息
#4.Looper.loop()结束死循环的条件是什么?
1.程序退出
2.MessageQueue # quit(boolean) 被调用 【非UI线程才能使用】
网友评论