简介
Handler用于线程间的通信,即异步消息的处理,比如子线程下载文件/图片,完成后通知主线程UI更改等等。handler用于发送消息和处理消息。当子线程的handler发送消息时,消息会被送往主线程的消息队列中(MessageQuene),等待Loop提取消息给主线程的Hanler处理。
为什么要设置通过Handler来更新UI,不用行吗?
android在设计的时候,就已经封装了一套完善的消息创建、传递、处理机制,如果不遵循这种机制就会抛异常。而设置这样机制最根本的问题是解决多线程并发带来的一些列问题。比如,一个UI中有多个线程同时对同一个控件进行更改样式的操作,那这个控件就会很混乱,无法控制。如果我们对所有更新UI的操作都做枷锁处理,其性能也会大打折扣。为了解决这样的问题,handler就诞生了,这使得我们在更新UI的时候不需要关心多线程问题。通常情况下,UI更新必须在主线程中进行的,当子线程需要更新UI时,就需要通过Handler发送消息到主线程的消息队列中排队等待处理。
子线程中更新UI的几种方式:
一、使用runOnUiThread方式:
二、通过Handler.sendMessage更新UI
PS:为了避免内存泄露,在ondestroy的时候加下面这句:
三、通过Handler.Post更改UI
四、通过view.post更改UI
子线程更改UI基本就是上面4中,看看Handler的工作原理
Handler原理
在说明原理前,我们需要了解他的成员以及作用
Handler:发送 / 处理 消息
Looper:消息封装的载体,类似于一个加工厂。
MessageQueue:存放众多消息,在Looper内部,类似于纽带。
Message:消息,类似于工作的物品。
handler首先发送消息到Looper工厂里面的纽带上,纽带很长,在工厂里面有一个抓手(Looper.Loop())这个抓手负责不断的从纽带上提取物品(message),当没有物品时,抓手就停止工作(阻塞),抓手抓到的东西在送往主线程的Handler去处理。
HandlerThread是什么
handlerThread会创建一个含有looper的handler,避免空指针异常。
在子线程创建Handler
在上面的代码中,handler都是在主线程创建的,下面试试在子线程创建hander,并让他往主线程发送消息。
首先创建MyThread线程
我们在子线程穿件ThreadHandler,这是子线程的Handler,在run中让子线程发送消息,在子线程中处理,ThreadHandler的处理就是把消息发送给主线程的handler。让主线程去处理哈~下面的截图是主线程的handler。
在主线程调用更改创建的子线程子线程是一定不能更改UI吗?
其实不是的,子线程子所以不能改UI,是因为Android在线程的方法里面采用checkThread进行判断是否是主线程,而这个方法是在ViewRootImpl中的,这个类是在onResume里面才生成的,因此,如果这个时候子线程在onCreate方法里面生成更新UI,而且没有做阻塞,就是耗时多的操作,还是可以更新UI的。但是不推荐这么做!
网友评论