- 1、IdleHandler是MessageQueue里面的一个内部接口,在MessageQueue的next()方法(next()方法用来从MessageQueue中取Message)中调用;
public static interface IdleHandler {
/**
* Called when the message queue has run out of messages and will now
* wait for more. Return true to keep your idle handler active, false
* to have it removed. This may be called if there are still messages
* pending in the queue, but they are all scheduled to be dispatched
* after the current time.
*/
boolean queueIdle();
}
queueIdle()方法在MessageQueue中没有消息时,才会回调;
返回值为false时,只会在循环取消息时,第一次没有消息时回调;
返回值为true时,每次在循环去消息时,没有消息时都会回调此方法;
- 2、HandlerThread继承于Thread,只不过HandlerThread在启动start后,会在内部主动创建这个线程持有的Looper,并且开启Looper.loop();
//HandlerThread中的run方法
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
因此可以获取通过handlerThread.getLooper()获取looper,来创建一个子线程的Handler;
具体的使用实例:
package com.zcbl.airport_assist.permissiondemo;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.util.Log;
import java.lang.reflect.Field;
/**
* Created by serenitynanian on 2018/10/18.
* 这个类主要用来演示HandlerThread和IdelHandler的用法
* HandlerThread实现了子线程通知主线程的功能
*/
public class HandlerThreadAndIdlelHandler implements MessageQueue.IdleHandler {
private static final String TAG = "HandlerThreadAndIdlelHandler";
private final Handler handler;
private MessageQueue queue;
private ChangeListener listener ;
public void setListener(ChangeListener listener) {
this.listener = listener;
}
public interface ChangeListener{
void onChange();
}
public HandlerThreadAndIdlelHandler() {
//参数为指定线程名字
HandlerThread handlerThread = new HandlerThread("handlerThread");
handlerThread.start();
Looper looper = handlerThread.getLooper();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//MessageQueue ,只能在6.0以上才能使用此方法获取MessageQueue
queue = looper.getQueue();
}else{
//6.0以下通过反射获取MessageQueue
Class<Looper> looperClass = Looper.class;
Field mQueue = null;
try {
mQueue = looperClass.getDeclaredField("mQueue");
mQueue.setAccessible(true);
queue = (MessageQueue) mQueue.get(looper);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
//注册idleHandler
queue.addIdleHandler(this);
//通过子线程的Looper创建一个子线程的Handler
handler = new Handler(looper){
@Override
public void handleMessage(Message msg) {
//因为是子线程的Looper,这个handlerMessage运行在子线程中
Log.i(TAG, "同步数据.....");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
/**
* idleHandler接口的方法
* @return
* 返回true 进入闲置就会回调此方法
* 返回false 进入闲置只会回调一次此方法
*/
@Override
public boolean queueIdle() {
//等待所有的消息都分发出去后,messageQueue进入闲置状态,才会回调此方法
if (null != listener) {
listener.onChange();
}
return true;
}
/**
* 释放idleHandler
*/
public void releaseIdleHandler(){
if (null != queue) {
queue.removeIdleHandler(this);
}
}
/**
* 外界调用此方法 使用子线程中的handler发送消息
*
* 外界可以连续调用此方法,让子线程中的handler处理耗时操作,等所有消息链表中的消息分发完成后,
* 才会回调IdleHandler中的queueIdle方法;这样就能实现一个子线程连续执行几个耗时任务,等所有的任务都执行了,
* 才通知外界,所有的任务都执行完毕;
*/
public void async(){
handler.sendEmptyMessage(0);
}
}
具体的调用:
HandlerThreadAndIdlelHandler handlerThreadAndIdlelHandler = new HandlerThreadAndIdlelHandler();
Handler handler = new Handler();
private void userHandlerThreadAndIdleThread() {
handlerThreadAndIdlelHandler.setListener(new HandlerThreadAndIdlelHandler.ChangeListener() {
@Override
public void onChange() {
//这个是在子线程中
handler.post(new Runnable() {
@Override
public void run() {
Log.i(TAG, "接收子线程中发送过来的消息,更新UI");
}
});
}
});
}
//持续点击几次,也就是执行多任务
public void click(View view) {
handlerThreadAndIdlelHandler.async();
}