异步消息处理机制

Handler

Android中的异步消息处理主要由4个部分组成:Message、Handler、MessageQueue、Looper

Looper负责的就是创建一个MessageQueue,然后进入一个无限循环体不断从该MessageQueue中读取消息,而消息的创建者就是一个或多个Handler

  • Message

    Message 是在线程之间传递的消息。

  • Handler

    处理着,主要用于发送和处消息的,sendMessage(),handleMessage()

  • MessageQueue

    消息队列,用于存放所用通过 Handler 发送的消息,这部分消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个 MessageQueue 对象。

  • Looper

    Looper 是每个线程中的管家,每当发现 MessageQueue 中存在一条消息,就会将它取出,并传递到 Handler 的 handleMessage() 方法中,每个线程也只有一个 Looper 对象。

异步消息处理机制详解——鸿洋大神的博客

Android异步消息处理机制完全解析——郭霖大神博客

Looper

对于Looper主要是prepare()和loop()两个方法

Looper主要作用:
1、 与当前线程绑定,保证一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue。
2、 loop()方法,不断从MessageQueue中去取消息,交给消息的target属性的dispatchMessage去处理。

Handler的一些方法

sendMessage 方法

  • sendMessage(Message msg)
  • sendEmptyMessageDelayed(int what, long delayMillis)
  • sendMessageDelayed(Message msg, long delayMillis)
  • sendMessageAtTime(Message msg, long uptimeMillis)

Handler post

  • post(Runnable r)

另外除了发送消息之外,我们还有以下几种方法可以在子线程中进行UI操作:

  1. Handler的post()方法
  2. View的post()方法
  3. Activity的runOnUiThread()方法

流程

  1. 首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
  2. Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
  3. Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue相关联。
  4. Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
  5. 在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。

那么在Activity中,我们并没有显示的调用Looper.prepare()和Looper.loop()方法,为啥Handler可以成功创建呢,这是因为在Activity的启动代码中,已经在当前UI线程调用了Looper.prepare()和Looper.loop()方法。

AsyncTask

郭神博客详解

参数

由于AsyncTask是一个抽象类,所以如果我们想使用它,就必须要创建一个子类去继承它。在继承时我们可以为AsyncTask类指定三个泛型参数,这三个参数的用途如下:

  1. Params
    在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。
  2. Progress
    后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
  3. Result
    当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。

需重写方法

  1. onPreExecute()
  2. doInBackground(Params…)
  3. onProgressUpdate(Progress…)
  4. onPostExecute(Result)

有一个问题,就是如果我们的Activity正在后台执行一个任务,可能耗时较长,那用户可能会点击返回退出Activity或者退出App,那么后台任务不会立即退出,如果AsyncTask内部有Activity中成员变量的引用,还会造成Activity的回收延时,造成一段时间内的内存泄露,所以我们需要加上:onPause中判断应用是否要退出,从而决定是否取消AsyncTask执行。