安卓开发中Handler消息传递机制

来源:互联网 发布:淘宝客退款还算佣金吗 编辑:程序博客网 时间:2024/06/05 03:47

        在安卓开发中,经常会遇到让程序在运行过程中修改界面属性的问题,然而当我们试图用其他线程机制(如timer线程)去修改界面属性时,会经常出现程序挂掉的问题,这也让好多初学安卓开发的人感到莫名其妙。

        在我们深入了解一些安卓开发机制之后,就会明白出现这样问题的原因:出于性能优化考虑,安卓的UI操作并不是线程安全的,尤其是有多个线程并发操作UI组件时,可能导致线程安全问题。为了安全问题考虑,安卓制订了一条简单的规则:只允许UI线程修改Activity里的UI组件。

        当一个程序第一次启动时,安卓会同时启动一条主线程(Main Thread),主线程负责处理与UI相关的事件,如按键事件、接触屏幕事件及屏幕绘图事件等,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。

        安卓的消息传递机制是另一种形式的“事件处理”,这种机制主要是为了解决安卓应用的多线程问题——安卓平台只允许UI线程修改Activity里的UI组件,这样就会导致新启动的线程无法动态改变界面组件的属性值。但在实际安卓应用开发中,尤其是需要让新启动的线程周期性地改变界面组件的属性值,这就需要借助于Handler消息传递机制来实现了。下面就给大家分享一下Handler消息传递机制的一些内容。

        1、Handler类:主要有两个作用:在新启动的线程中发送消息;在主线程中获取和处理消息。

              然而,在新启动的线程中发送消息,再在主线程中获取和处理消息的时机并不好控制。所以在这里只能通过回调的方式来实现——只需重写Handler类中的处理消息的方法,当新启动的线程发送消息时,消息会发送到与之关联的MessageQueue,而Handler会不断地从MessageQueue中获取并处理消息——这时Handler类中处理消息的方法会被回调。

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

             * 处理消息的方法:void handlerMessage(Message msg)

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

             *检查消息队列中是否包含what属性为指定值且object属性为指定对象的消息:finally boolean hasMessages(int what,Object object)

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

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

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

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

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

        2、Handler、Loop、MessageQueue的工作原理:

             为了更好地理解Handler的工作原理,先介绍一下与Handler一起工作的几个组件。

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

             Looper:每个线程只能拥有一个Looper。它的Loop方法负责读取MessageQueue中的消息,读到信息之后就把消息交给发送该消息的Handler进行处理

             MessageQueue:消息队列,它采用先进先出的方式来管理Message。程序创建Looper对象时会在它的构造器中创建Looper对象。

             程序使用Handler发送消息时,被Handler发送的消息必须被送到指定的MessageQueue,否则消息无法保存。而MessageQueue是由Looper负责管理的,即必须在当前线程中有Looper对象,可以分如下两种情况处理:

             1)主UI线程中,系统已经初始化了一个Looper对象,因此程序直接创建Handler即可,然后就可通过Handler来发送和处理消息。

             2)程序员自己启动的子线程,必须手动创建一个Looper对象,并启动它。创建Looper对象调用它的prepare()方法即可。该方法可以保证每个线程最多只有一个Looper对象。

             然后调用Looper的静态loop()方法来启动它。loop()方法使用了一个死循环不断取出MessageQueue中的消息,并将取出的消息分给该消息对应的Handler进行处理。

             至此。我们可以总结在线程中使用Handler的步骤:

             1)调用Looper的prepare()方法为当前线程创建Looper对象,它的构造器会创建与之配套的MessageQueue。

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

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

              在我的另一篇博文“安卓动态曲线的绘制”和我上传的“闪光灯频闪测试” 源码中对Handler机制都有使用,大家可以作为实例来参考理解。          

0 0
原创粉丝点击