介绍:
Handler机制指的是Android的消息机制,它的使用很简单,通过它可以轻松的将一个任务切换到Handler所在的线程去执行,我们用的最多的地方也就是Handler刷新UI的功能,其实,它还有很多用途,比如子线程中进行消耗的I/O操作,读取文件等,而我们用它来刷新UI,是因为子线程无法刷新UI,可以通过它来切换回主线程执行,因此,本质来说,它只是常用来刷新UI而已
Handler机制
Handler机制也就是消息机制,它与MessageQueue和Looper完成一个体系.
MessageQueue
从字面意思我们不难知道,它是个消息队列,也就是说,它存储了所有的消息,也可以叫它消息列表,我们从Handler的sendMessage发出的消息都会被存储到这里面
Looper
Looper翻译成中文就是循环,意思就是消息循环,它会无限循环的从MessageQueue中读取消息,如果有则处理,没有就一直等待,MessageQueue虽然是消息队列,然而它并没有能对消息进行处理的操作,因此,需要Looper的支持
Handler
Handler主要负责发送消息到MessageQueue,它在创建的时候,会采用当前线程的Looper来构成消息系统,但是注意了,线程默认是没有Looper的,而使用Handler就一定需要有Looper才可以执行,主线程之所以能使用Handler,那是因为主线程是ActivityThread,ActivityThread被创建的时候会初始化Looper,所以它能使用Handler,所以主线程也叫UI线程
所以,我们大概就知道了Handler是怎么工作的了,Handler创建完之后,通过Handler的send方法将一个消息存储到MessageQueue中,然后Looper循环从MessageQueue中读取消息并且处理,处理完之后如果还有消息就继续处理,否则就等待
上面就是Handler和MessageQueue,Looper的关系,这三者其实是一个整体,我们来思考下几个问题,①:为什么不能再子线程中更新UI,②:为什么需要用Handler来刷新UI,③:如果非要在子线程中更新UI怎么办,现在我们来说说这几个问题
问题一:
之所以Android不允许在子线程中更新UI,那是因为,子线程是可以无限被创建的,我们假想下,如果有5条子线程,每条子线程都有一个UI控件,我们去刷新UI的时候会出现什么后果,后果就是我们达不到预期的UI控件刷新顺序,我们可能想控件1先刷新控件2再刷新,有可能就会出现相反的顺序,也可能同时刷新,并且,如果有N条子线程,线程并发问题会更严重,所以Android必须要在UI线程中更新UI,也有可能会问,为什么不对UI控件上锁呢?原因有两个:1,上锁会让UI访问逻辑复杂化,不灵活,如果我需要在其他线程访问UI的话,比较难处理 2,加锁会阻塞线程的执行,所以,这就是为什么我们需要在UI线程中更新UI的原因
问题二:
我们知道,在异步线程中访问网络请求之后,需要刷新UI的时候是不能再子线程中执行的,Handler可以做到刷新UI,那是因为Handler在创建的时候会调用当前线程的Looper对象,Looper对象是对消息的处理,所以,我们执行完请求之后,可以切换回主线程,调用主线程的Looper对象去刷新UI,这里要注意了,因为Handler会调用当前线程的Looper对象,所以Handler需要在主线程中创建,否则会报错的,所以总的来说,Handler更像一个切换线程的类
问题三:
如果我们非要在子线程中去刷新UI,也不是没有办法,我们可以创建一个Looper,然后去获取主线程的Looper对象即可,又或者可以在一个有Looper的线程中创建Handler也可以,但是这样就毫无意义了,所以总的来说,当我们需要使用Handler的时候,就在UI线程中去创建,我们来看看怎么获取主线程的Looper对象和创建Looper对象