什么是Handler?
Handler主要用于异步消息的处理,当发出一个消息后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分在消息队列中逐一将消息取出,然后对消息进行处理。
子线程进行耗时操作>>>>>>>>>sendMessage(Message)>>>>>>>>UI线程
1.handler内存泄漏测试
2.为什么不能在子线程创建handler
3.textview.setText(" ")只能在主线程执行是错误的。
4.new handler()两种写法的区别
5.ThreadLocal的用法和原理
answer1 在子线程中发送消息时,如果要延时采用sendMessageDelayed(),当onDestory()时,removeMessage(),或者SyetemClock.sleep()系统延迟时,在onDestory()时,将handler=null置空
answer2 其实在有些手机上面是可以的,因为厂商在底层修改了源码,但是原生系统中,当new hander时,threadLocal回去threadLocalMap中去取looper,而looper是全局的唯一变量已经给了主线程,当子线程再去去的时候就已经取不到了。
answer3 其实setText(" ")执行速度当刷新页面的速度快于checkThread()的速度就不会抛异常,如果延时或者采用土司就会抛出异常。为了保险起见在子线程中不应该setText(" "),但是这种说法太过绝对。
answer4 一种是重写handlerMessage(),另一种是将回调接口CallBack当作参数传入new Handler构造方法。
answer5 从threadLocalMap中获取key value。key是线程,value是looper。ThreadLocal有一个全局唯一静态变量,当ThreadActivity创建时就已经创建。
Handler原理,工作流程
第一步:ActivityThread中的main(),Looper.prepareMainLooper()>>>>prepare()>>>>sThreadLocal.set(new Looper)创建全局唯一Looper对象,在Looper构造方法中{new MessageQueue()}创建全局唯一消息队列
第二步:在activity中,new Handler()重写handlerMessage();在创建对象的过程中,将全局的messageQueue对象赋值给Handler中的messageQueue,再从全局线程池中取出主线程Looper,sThreadLocal.get()。
发送消息 handler.sendMessage(message)>>>>将消息放入队列中,queue.enqueueMessage(msg)>>>>mMeeages=msg
取消息 ActivityThread中的main(),looper.loop()中有一个轮询器一直在工作//获取looper对象 Looper me=getLooper(),获取消息队列,MessageQueue queue=me.mQueue;//从消息队列取出消息Message msg=mQueue.next();调用handler的方法,msg.targe.dispatchMessage(msg);
自己手写Handler流程源码,只是一个大致工作流程,不考虑健壮性等因素
1.ActivityThread
public class ActivityThread {
@Test
public void main() {
//创建全局唯一的,主线程的Looper对象,以及messageQueue消息队列对象。
Looper.prepare();
//模拟activity中,创建handler对象
final Handler handler =new Handler() {
@Override
public void handlerMessage(Message message) {
super.handlerMessage(message);
System.out.println(message.obj.toString());
}
};
//消费消息,回调方法(接口方法)
//子线程发送消息
new Thread(new Runnable() {
@Override
public void run() {
Message messa=new Message();
messa.obj="hello handler";
handler.sendMessage(messa);
}
}).start();
//轮询。取出消息
Looper.loop();
}
}
2.Looper
public class Looper {
public MessageQueuemQueue;
static final ThreadLocalsThreadLocal =new ThreadLocal<>();
private Looper() {
mQueue =new MessageQueue();
}
public static void prepare() {
//主线程唯一一个Loop对象
if (sThreadLocal.get() !=null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//应用启动时,初始化赋值
sThreadLocal.set(new Looper());
}
//轮询,提取消息
public static void loop() {
//从全局ThreadlocalMap()中获取全局唯一Looper对象
Looper me =getLooper();
//从Looper对象中获取全局唯一的消息队列对象
final MessageQueue queue = me.mQueue;
Message resultMessage;
while (true) {
Message msg = queue.next();
if (msg !=null) {
msg.targe.dispatchMessage(msg);
}
}
}
public static LoopergetLooper() {
return sThreadLocal.get();
}
}
3.Message
public class Message {
public Objectobj;
public Handlertarge;
@Override
public StringtoString() {
return obj.toString();
}
}
4.//消息队列
public class MessageQueue {
//阻塞队列
BlockingQueueblockingQueue =new ArrayBlockingQueue<>(50);
//将message存入消息队列
public void enqueueMessag(Message message) {
try {
blockingQueue.put(message);
}catch (InterruptedException e) {
e.printStackTrace();
}
}
//从消息队列取出message
public Messagenext() {
try {
return blockingQueue.take();
}catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}
5Handler
public class Handler {
private LoopermLooper;
private MessageQueuemQueue;
public Handler() {
mLooper = Looper.getLooper();
if(mLooper==null){
throw new RuntimeException("Can't create handler inside thread " + Thread.currentThread()
+" that has not called Looper.prepare()");
}
mQueue=mLooper.mQueue;
}
public void handlerMessage(Message message) {
}
public void sendMessage(Message message) {
enqueueMessage(message);
}
private void enqueueMessage(Message message) {
message.targe=this;
mQueue.enqueueMessag(message);
}
public void dispatchMessage(Message msg) {
handlerMessage(msg);
}
}