Android学习自记 之 Handler

来源:互联网 发布:临沂盛誉seo 编辑:程序博客网 时间:2024/06/05 20:46

  • HandlerLooperMessageQueue Thread 这三个class紧密相关的:默认情况下,一个新创建的Thread对象是没有循环消息队列可用的,当在该线程中创建了Looper对象(可直接调用静态方法 Looper.prepare() 来实现创建)后,该Looper对象默认会有一个MessageQueue对象与之绑定,从而该线程也就拥有了一个MessageQueue。

  • 在Thread对象中,除了创建Looper之外,还需要调用 Looper.loop() 这个静态方法才能启动该线程的消息队列。为了简化此工作,android系统提供了 HandlerThread 这个Thread的子类,可直接创建一个具有已激活消息队列的线程,该线程默认的run( ) 方法只做一件事情,即处理来自该线程MessageQueue的Message和Runnable对象。

  • 当一个线程具有了消息队列之后,就可以创建一个Handler对象与该线程及该线程的消息队列绑定。Handler最基本的创建方式有两种:
    1.   new Handler() ——这种方式下,Handler对象与当前线程及其消息队列绑定
    2.    new Handler(Looper looper) ——这种方式下Handler对象与该Looper对象所在的线程及其消息队列绑定
          ( PS:一个HandlerThread线程是可以通过 getLooper() 得到其关联的Looper对象)

  • 一个线程的消息队列实际可以看作包含两个queue结构,一个queue存放Message对象,另外一个queue存放Runnable对象。当一个Handler对象与某线程绑定之后就可以通过该Handler对象向线程的消息队列中添加Message或Runnable对象了

  • Handler对象向线程的消息队列中添加Runnable对象是通过Handler对象的post系列方法来实现的,最常用的包括 post(Runnable r)postAtTime(Runnable r, long uptimeMillis) 和 postDelayed(Runnable r, long delayMillis)  通过这些方法可以实现Runnable对象的 run( ) 方法在该线程中的定时执行。
    个人谨记
    1.    无论采用哪种post方法,Runnable被Handler加入到线程消息队列的动作是立即完成的,带有时间参数的postDelayed或者postAtTime方法指定的是Runnable的run()方法在线程中被调用的时间,而不是Runnable对象加入消息队列的时间。

    2.    post系列方法加入到消息队列中的Runnable对象并不是按照调用post的顺序被执行的,即如下的代码段
    handler.postDelayed(r1, 5000);
    handler.postDelayed(r2, 1000);
    handler.post(r3);

    执行的顺序是 r3.run(),r2.run(), r1.run()。??这似乎与queue“先进先出”的原则不符合,个人只能在此暂时理解为使用postDelayed()方法的Runnable对象在Runnable Queue中被置后了

  • Message包含 int arg1 int arg2,  int what,  Object object 这几个成员变量, 可用作Message中简单信息的高效传递。比较复杂的数据则可以通过Message中的 setData(Bundle data) 来实现,Bundle 其实就是 key 为String类型,value类型众多的Map类

            一个空 Message 对象是通过 Handler 对象的 obtainMessage() 方法从特定线程的Looper创建的message pool中获得的,也就是说一个Message在创建之初就已经与一个Handler、一个线程绑定关联的。Message内容被确定后添加到线程的消息队列有两种方式:

    1.     通过与Message相关的Handler对象的send系列方法来实现的,最常用的包括 sendEmptyMessage(int what),

    sendEmptyMessage(int what), sendEmptyMessage(int what), 

    sendEmptyMessageDelayed(int what, long delayMillis)

    sendMessage(Message msg) 和 sendMessageDelayed(Message msg, long delayMillis)

    2.      直接调用Message对象的 sendToTarget() 方法。

    个人谨记:

    Message与Runnable进入消息队列的方式不同。之前提到过无论采用哪种post方法,Runnable进入线程消息队列的动作都是立即完成的,postDelayed()方法delay的只是他们的run()方法被线程执行的时间;
           而Message就不同了,sendMessageDelayed() 方法延迟的直接是Message排入消息队列的时间MessageQueue严格的遵循“先进先出”的原则

  • Handler对象通过其 public void handleMessage(Message msg)  方法不停地在其绑定线程中处理线程消息队列(准确的说是Message Queue)中的Message

  • Handler将 Message 或 Runnable 放入线程的消息队列这个动作,与线程处理这些Message或执行Runnable的run()方法的动作—— 是异步的,即在当前线程中执行Handler将Message或Runnable放入消息队列的语句之后,当前线程就顺序执行下去,执行过程不会受到消息处理的影响。

  • 实际上,在android文档中可以看到每一个所有的View都运行和被操作在UI线程中,而UI线程有一个UI Events Queue。因此UI主线程处理用户的交互操作等events,同样是将这些events看作是放入消息队列的Message,如果Handler就是与UI主线程绑定的,那么Handler放入消息队列的 Message 或 Runnable 的处理就和用户交互events处理按照一定的调度算法互相竞争CPU,可能会导致UI主线程响应用户感观变差。
           如果将Handler与UI线程之外的其他线程绑定,则Handler对象添加的Message或Runnable的处理都在另外的线程中,就不会影响UI线程了
            

原创粉丝点击