您的位置:首页 > 其它

Handler 消息传递机制的理解与学习

2014-07-07 08:35 141 查看
UI线程

Android 程序首次启动时会同时启动一条主线程(Main Thread),主线程主要负责处理与 UI 相关的事件如按键事件、触屏事件、屏幕绘图事件等,并把相关事件分发到对应的组件进行处理。所以主线程又称 UI 线程。

出于性能考虑,Android 的 UI 操作并不是线程安全的,这意味着若有多个线程并发操作 UI 组件,可能会导致线程安全问题。因此 Android 平台只允许 UI 线程修改 Activity 里的 UI 组件。新启动的线程若需动态改变界面组件和属性值,只能借助于 Handler 消息传递机制来实现——这种机制可以看作是另一种形式的“事件处理”。

也就是说, Handler 消息传递机制,对于界面组件属性的修改,只授权给应用程序的主线程。其他线程若需改变界面组件属性,则只能给主线程发送消息(打申请),主线程会依次处理消息序列,并按相关规则执行或取消修改动作。

Handler 类的认识

Handler 类的主要作用有两个:

在新启动的线程中发送消息。

在主线程中获取、处理消息。

这个类的使用及原理:

开发者重写 Handler 类中处理消息的方法;

当新启动的线程发送消息时,消息会被发送到与之关联的消息队列 MessageQueue;

Handler 会不断地从消息队列 MessageQueue 中获取并处理消息——这将导致 Handler 类中处理消息的方法被回调。



Handler 类包含如下方法用于发送、处理消息:

void handleMessage(Message msg) :处理消息的方法,通常用于被重写。

final boolean hasMessages(int what) :检查消息队列中是否包含 what 属性为指定值的消息。

final boolean hasMessages(int what, Object object) :检查消息队列中是否包含 what 参数为指定值且 Object 参数为指定对象的消息。

Message obtainMessage() :获取消息(多个重载)。

sendEmptyMessage(int what) :发送空消息。

final boolean sendEmptyMessageDelayed(int what, long delayMillis) :指定 delayMillis 毫秒之后发送空消息。

final boolean sendMessage(Message msg) :立即发送消息。

final boolean sendMessageDelayed(Message msg, long delayMillis) :指定 delayMillis 毫秒之后发送消息。


与 Handler 一起工作的几个组件:

Message :Handler 接收和处理的消息对象。

Looper :每个线程拥有一个 Looper。它的 loop 方法负责不断地读取 MessageQueue 中的消息,获取消息后分给对应的 Handler 进行处理。

MessageQueue :消息队列,采用先进先出的方式来管理 Message。程序创建 Looper 对象时会在 Looper 的构造器中创建与之关联的 MessageQueue 对象,这个 MessageQueue 就负责管理消息。

Handler :其作用有两个——把消息发送给 Looper 管理的 MessageQueue,并负责处理 Looper 分给它的消息。

为确保发送的消息能到达消息队列 MessageQueue,须先保证当前线程存在消息队列的创建者 Looper。处理方式分两种情况:

主 UI 线程中由系统初始化一个 Looper 对象,此时程序直接创建 Handler ,即可通过 Handler 来发送消息、处理消息。

程序员自己启动的子线程,须自己创建一个 Looper 对象并启动它。

创建方法:

prepare() :该方法会保证每个线程最多只有一个 Looper 对象。

然后调用 Looper 的静态方法 loop() 来启动它。

在线程中使用 Handler 的步骤如下:

调用 Looper 的 prepare() 方法为当前线程创建 Looper 对象。(此时 Looper 的构造器会自动创建与之关联的 MessageQueue)

创建 Handler 子类的实例,重写 handleMessage() 方法,以负责处理来自于其他线程的消息。

调用 Looper 的 loop() 方法启动 Looper。


注:执行需要消耗大量时间的操作一般应新开线程来执行,而尽量避免在 UI 线程中执行,否则容易导致 Android 应用程序无法响应输入事件和 Broadcast 而引发 ANR 异常(Application Not Responding)。

PS:

show.setImageResource(imageIds[currentImageId++% imageIds.length]);

上面这条代码,imagesIds 是一个数组,通过取余数的写法,可以不断的循环结构中不断的读取数组内容,而不用考虑数组越界的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: