出现的原因
大家都知道在android中UI线程是不允许被阻塞的,如果阻塞会造成UI卡顿,并且时间超过5秒会发生ANR。所以有些耗时的任务必须要放到异步任务中,但是当异步任务完成得时候又要进行UI操作,然而由于当前线程不是主线程(UI线程)是没有办法进行UI更新的。为了解决这个问题google提供了一种消息传递机制--Handler。可以理解为它是工作线程和UI线程的中间人。
什么是Handler
Handler是Google给我开发者提供的一套处理消息的消息机制,可以通过它发送消息和处理消息。主要是对Message和Runable的处理,并且可以指定在特定的时间进行处理
Handler应用
1.在主线程中声明Handler
调用post发送消息
此处,调用handler发送消息是在异步线程,但是Runable中的方法是在主线程中执行,并且发送消息后不会调用handler的handleMessage方法,至于原因在讲解handler源码时会讲解
通过sendMessage方法发送消息
此处同样的道理调用是在异步线程,但是执行也在主线程,并且会回调handleMessage方法
2.在异步线程声明Handler
此时点击运行报错如下:
意思是在异步线程中创建Handler时,必须要先调用Looper.prepare()方法,至于原因在讲解源码时讲,现在我们先把这段代码加上,让程序运行起来
在上面的代码中我们在创建Handler前加上了Looper.prepare()这是为了处理上面的错误。
在创建完成后调用了Looper.loop()方法,这个是开启消息循环,不然就算发送了消息也不会处理,代码跑起来了,注意下面这个打印日志:
此处Handler的是在线程名称为Thread-2中创建的,并非是在主线程,现在来发送消息
调用post发送消息:
此处注意发送消息是在一个异步线程,并且也没有回调handleMessage方法,但是Runable中的方法并不是运行在主线程,而是在Thread-2这个线程也就是创建Handler的线程,这是为嘛呢?先不慌再来看通过sendMessage发送消息
同样是在异步线程发送消息,并且回调了handleMessage方法,但是也不是在主线程处理消息。这尼玛到底是什么情况,不是说handler会在主线程处理嘛,这样子还怎么更新UI。
到这里相信很多同学都有很多疑惑了,那到底为什么会这样子呢,等下节讲Handler源码的时候会详细讲解。
到此我们已经知道如果想要handler处理的Message或者Runable在主线程中进行处理并可以更新UI则handler必须在主线程中声明。
当在异步线程中创建handler时还有一种情况,即同一个线程中第二次调用Looper.prepare()会抛出以下错误
对于以上的错误和没有按照我们想法进行的问题,在下面讲解源码时会一一为大家解惑。