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 对象。
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操作:
- Handler的post()方法
- View的post()方法
- Activity的runOnUiThread()方法
流程
- 首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
- Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
- Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue相关联。
- Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
- 在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。
那么在Activity中,我们并没有显示的调用Looper.prepare()和Looper.loop()方法,为啥Handler可以成功创建呢,这是因为在Activity的启动代码中,已经在当前UI线程调用了Looper.prepare()和Looper.loop()方法。
AsyncTask
参数
由于AsyncTask是一个抽象类,所以如果我们想使用它,就必须要创建一个子类去继承它。在继承时我们可以为AsyncTask类指定三个泛型参数,这三个参数的用途如下:
- Params
在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。 - Progress
后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。 - Result
当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。
需重写方法
- onPreExecute()
- doInBackground(Params…)
- onProgressUpdate(Progress…)
- onPostExecute(Result)
有一个问题,就是如果我们的Activity正在后台执行一个任务,可能耗时较长,那用户可能会点击返回退出Activity或者退出App,那么后台任务不会立即退出,如果AsyncTask内部有Activity中成员变量的引用,还会造成Activity的回收延时,造成一段时间内的内存泄露,所以我们需要加上:onPause中判断应用是否要退出,从而决定是否取消AsyncTask执行。