直接翻译官方API文档:

public class Handler extends Object

概述

Handler允许你发送或者处理与某个线程(Message Queue)相关联的Message或者是Runnable对象。每个Handler实例只能与一个线程(Message Queue)相关联。当你创建一个Handler时,它就与创建Handler所在的线程/线程Message Queue绑定在一起———从这个时候开始,Handler把Messages或者Runnable交付给这个线程的Message Queue

Handler有两种主要的用法:

  • 发送消息或者Runnable,他们将在未来某些时候被执行
  • 从另外一个线程中,将一个要被执行的动作,加入到消息队列

发送消息通常使用如下方法来完成:
post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable, long), sendEmptyMessage(int), sendMessage(Message), sendMessageAtTime(Message, long), sendMessageDelayed(Message, long)

其中,post相关的方法允许你加入一个Runnable对象到消息队列,并且当消息队列收到时开始执行Runnable;send相关的方法允许你加入一个Message对象,该对象包含一个Bundle数据,并且在Handler的handleMessage方法中进行处理(这要求你实现一个Handler的子类)。

当你发送一个Message或者Runnable时,你可以指定消息队列立刻开始处理,你也可以让Message Queue在合适的时间Delay进行处理。

当一个进程被应用启动时,他的主线程(Main Thread或者称为UI线程)将会有一个专用的Message Queue,负责管理最顶层的控件(例如activity,broadcast receiver等)和他们生成的一些窗口。你可以创建你自己的线程,并通过Handler来与主线程进行通信,这也是通过上面提到的post或者sendMessage方法来实现的,只不过是从你自己的线程中发送出来。给定的Runnable或者Message将会被安排到这个Handler所在线程的Message Queue中,并在合适的时候处理他们。

解决疑问:Runnable是在新线程中执行的吗?
答:Runable不是启动一个线程,当调用handler.post(runable)的时候,handler会将runnble插入到handler所在线程的消息队列中,并且在该线程中执行runnable。这也就解释了为什么有时候可以在Runnable的run方法中更新UI的疑问。因为run真正执行的线程,是handler所在的线程。
使用new Thread(Runnable),此时runnable才是在新的线程中执行的。

public final class Looper extends Object

概述

用于实现一个线程的消息循环,一个线程默认是没有消息循环与之相关联的,通过Looper.prepare()来开启(run)一个循环,并通过Looper.loop()来让它开始处理消息,直到loop被停止。
大部分与消息循环的相互作用是通过Handler来实现的。
下面是Looper线程一段典型的例子,通过Looper.prepare()和Looper.loop()来创建一个Handler与消息队列通信。

  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对象开始工作,从消息队列里取消息,处理消息          Looper.loop();      }  }

看下面的图

①Handler的职责是发送并处理消息

②Message Queue是一个消息队列,所有的消息都会被传入MessageQueue,然后按照先进先出原则被Looper取出

③Looper是一个消息泵,不停的从Message Queue中取出消息并发送给Handler处理。但是,looper工作是需要前提的:1.线程默认是没有Looper的,我们通过调用Looper.prepare()来创建一个Looper;2.Looper被创建之后并不会立刻开始工作,我们需要手动调用Looper.loop()来开启looper的消息循环,来不停的从消息队列中取出消息并发送给handler处理,直到调用handler.getLooper().quit()来终止looper的工作。

注意,在一个程序的主线程中(UI线程),系统会在main方法中为我们创建一个Looper,并开启此looper的循环,所以在主线程中我们不用手动调用Looper.prepare()以及Looper.loop().
请看源码android.app.ActivityThread类的main方法:

    public static void main(String[] args) {        // ...        // Other codes...        // 1.创建一个服务于主线程的Looper        Looper.prepareMainLooper();        ActivityThread thread = new ActivityThread();        thread.attach(false);        if (sMainThreadHandler == null) {            sMainThreadHandler = thread.getHandler();        }        if (false) {            Looper.myLooper().setMessageLogging(new                    LogPrinter(Log.DEBUG, "ActivityThread"));        }        // 2.启动消息循环        Looper.loop();        throw new RuntimeException("Main thread loop unexpectedly exited");    }

更多相关文章

  1. Android异步下载网络图片(其三)
  2. Handler: 更新UI的方法
  3. Android(安卓)AsyncTask 源码解析
  4. android中google“定位查询”
  5. Android(安卓)非UI线程使用View.post()方法一处潜在的内存泄漏
  6. Android(安卓)注解
  7. Android(安卓)AsyncTask和Handler对比
  8. Android中的消息通知-Toast和Notification
  9. Android-EventBus(手写简易版)

随机推荐

  1. Android xliff和字符串资源
  2. Small宝典(一)Android(安卓)Small框架源码
  3. 文件对应
  4. Android:+WebView+demo
  5. AIDL --- Android中的远程接口
  6. Android摄像头预览界面上画线
  7. Android对话框显示后自动消失
  8. Android(安卓)自定义Toast显示多种方式
  9. android访问网站
  10. Android Spinner 用PopupWindow实现