免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1044 | 回复: 0

Android101104:android.os包的简记(1): Handler [复制链接]

论坛徽章:
0
发表于 2011-01-05 10:45 |显示全部楼层
Android101104
android.os包的简记(1): Handler



Email:    zcatt@163.com
Blog    http://zcatt.cublog.cn

 
内容提要
文档简要整理android.os包的内容。以供备忘和参考。



声明
仅限学习交流,禁止商业用途。转载需注明出处。


版本记录
Date    Ver    Note
2011-01-04    0.1    Draft.  zcatt, Beijing
 
 
1.    Handler机制
Handler机制属于异步处理。典型的例子, 非ui线程要更新ui, 那么不应当直接操作ui的更新,而是应当将更新事件发送到ui的线程中,由ui线程进行更新ui操作。 更新事件中可以包括更新的方法或者回调。
android.os包中的Handler机制相关的类文件包括
    Handler.java
    MessageQueue.java
    Message.java
    Looper.java
    HandlerThread.java
Message用于封装事件消息,Looper代表了处理事件消息的循环。MessageQueue是个事件消息队列,接收的消息在这里排队,等待Looper的处理。HandlerThread是一个辅助类,用于方便创建带有looper的thread。
如图<android_os_handler>
下面分述之。

2.Message
Message封装的是事件消息。包含的属性主要有,
    Handler target;
    Runnable callback;
    long when;
    public int what;
    public int arg1;
    public int arg2;
    public Object obj;
    Bundle data;
其中,target和callback通常只有一个有效,用于说明谁(Handler)处理这个message或者使用什么回调(Runnable)来处理。如果message设定了callback,那么在处理message时将使用callback,而不使用Handler,但一般的使用方法都是设定Handler,使用Handler::handleMessage()处理消息。what, arg1, arg2, obj,和data是事件消息的具体内容,message的发送者和接收处理者可以通过这些传递信息,决定处理的动作。
特别注意,对于process间的传递message,obj必须是支持Parcelable的,而data应该使用Bundle.setClassLoader()设置了classLoader。
简而言之,Message对象中包含了谁处理(target,callback),处理什么(what,arg1,arg2,obj,data),和时间(when)的信息。
为了加速Message的分配和释放,Message维持了一个类message缓冲池,释放的message会放到缓冲池中,当申请新的message时,直接从缓冲池中取用。Message中有一个next域,可以用于链接message。

3.MessageQueue
MessageQueue是一个消息队列,message按照时间顺序在队列中排列,给定时间,可以方便的从队列中得到指定时间前的时间。MessageQueue的关键方法是
    final Message next();
    final Message pullNextLocked(long now);
next()返回队列中最前的message. pullNextLocked()返回指定时间以前的队列中最前的message.

4.Looper
Looper是handler机制的核心,它代表的是thread中的事件处理循环。一个thread通常按照下面的方式组装进Looper,就构成了真正处理message的thread。

    class LooperThread extends Thread {
      public Handler mHandler;
     
      public void run() {
          Looper.prepare();
         
          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };
         
          Looper.loop();
      }
    }
Looper对象生成并关联唯一一个MessageQueue,消息事件message被投递到MessageQueue,而真正的处理loop()方法则运行在自己的thread中,从MessageQueue中依次取出message进行派发处理,记得message中包含有“谁处理”的信息。
几个关键方法,
    public static final void prepare();
    public static final void loop();
    public static final Looper myLooper();
    public void quit();
注意前3个方法是static。Looper是运行在自己的thread中的,Looper使用了ThreadLocal来保存自己线程关联的(使用的)Looper对象,这也是prepare(),loop(),和myLooper()是static的原因。也就是说perpare(),loop()和myLooper()应该使用在自己的线程中。
prepare()负责创建一个looper对象,并保存在ThreadLocal变量中。
loop()负责实际的读取messageQueue并分发处理,实际是一个循环,出口条件是碰到一个target是null的message。这也是正常的message的target必须与一个handler关联,不能为0的原因。
myLooper()可以得到当前线程对应的looper对象,当然调用myLooper()前应当保证prepare()已经执行了。
quit()方法就是用于退出loop()的消息循环,从而结束处理线程。实现的方法就是构造一个target为null的message,并加入messageQueue

5.Handler

Handler必然跟一个Looper对象相关联,也就是跟一个messageQueue相关联。创建时,如果不指定,则默认是当前线程对应的Looper。
每个message都会跟一个Handler关联。Handler提供消息的处理方法。开发中需要继承Handler类,在派生类中通常实现handleMessage()方法。在handleMessage()中实现处理message的逻辑,handleMessage()会在Looper.loop()中被分发调用,处理message。当然如果message指定了callback,将使用callback方法处理message。
Handler是Handler机制中的编程接口,一般情况下,开发中无需关注Looper,MessageQueue,只要使用Handler就够了。
Handler还提供了几个obtainMessage()方法,便于开发者申请分配message对象,当然得到的message对象都已经跟Handler关联好了。
开发者申请分配message,得到message对象后,设定message的各信息域。接下来就是发送到messageQueue中,这个可以通过几个sendMessage和postMessage进行。send和post的区别在于,send的消息将使用Handler的handleMessage()方法处理message,而post将定义callback,使用callback处理message。下面罗列这些send,post方法,不详述。
    public final boolean post(Runnable r);
    public final boolean postAtTime(Runnable r, long uptimeMillis);
    public final boolean postAtTime(Runnable r, Object token, long uptimeMillis);
    public final boolean postDelayed(Runnable r, long delayMillis);
    public final boolean postAtFrontOfQueue(Runnable r);
    public final boolean sendMessage(Message msg);
    public final boolean sendEmptyMessage(int what);
    public final boolean sendEmptyMessageDelayed(int what, long delayMillis);
    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis);
    public final boolean sendMessageDelayed(Message msg, long delayMillis);
    public boolean sendMessageAtTime(Message msg, long uptimeMillis);
    public final boolean sendMessageAtFrontOfQueue(Message msg);

6.HandlerThread
HandlerThread是一个辅助函数,方便创建带有Looper的thread。

7. 使用方法

7.1自己新建专有消息处理thread的情况

1)使用HandlerThread创建looper thread

    HandlerThread myLooperThread;
    myLooperThread = new HandlerThread("my looper thread");
    myLooperThread.start();

2) 定义handler

    class MyHandler extends Handler {
        public myHandler(Looper looper) {
            super(looper);
        }

        public void handleMessage(Message msg) {

            // to do your processing

        }   
    }

    Looper looper = myLooperThread.getLooper();
    MyHandler myHandler = new MyHandler(looper);

3)发送事件消息

    Message msg;
    msg = myHandler.obtainMessage(...);

    //set msg fields
    msg.what = ...;
    msg.arg1 = ...;
    ...

    //send msg
    myHandler.sendMessage(msg);

    //or

    msg.sendToTarget();


7.2使用已有的thread,不创建自己的处理thread

1)定义handler

    class MyHandler extends Handler {
        public myHandler(Looper looper) {
            super(looper);
        }

        public void handleMessage(Message msg) {

            // to do your processing

        }   
    }

    Looper looper = Looper.myLooper();
    MyHandler myHandler = new MyHandler(looper);
2)发送事件消息
同上,不赘述。
 Locations of visitors to this page
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP