继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Handler详解(一)

龙西岳
关注TA
已关注
手记 7
粉丝 14
获赞 101

1、handler是什么?

2、为什么要用handler?

3、handler怎么用呢?

4、android 为什么要设计只能通过handler机制更新UI?

5、handler的原理是什么?

6、使用handler时候遇到的问题?

7、如何实现一个与线程相关的Handler?

8、HandlerThread又是什么?

9、如何在主线程给子线程发送消息呢?

10、android中更新UI的几种方式?

11、非UI线程真的不能更新UI吗?

12、使用handler时遇到的问题?

一、handler是什么?

Handler主要用于异步消息的处理: 有点类似辅助类,封装了消息投递、消息处理等接口。当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分在消息队列中逐一将消息取出,然后对消息进行处理,也就是发送消息和接收消息不是同步的处理。 这种机制通常用来处理相对耗时比较长的操作。

2、为什么要用handler?

为什么要用handler?不用这种机制行不行?不行!android在设计的时候,就封装了一套消息的创建、传递、处理机制,如果不遵循这种机制,就没有办法更新UI信息,就会抛出异常信息。

3、handler怎么用呢?

1)handler.post()

2)handler.postDelayed()

3)handler.sendMessage();

4)handler.sendEmptyMessage();

5)handler.removeCallback(runnable)

1)主线程创建handler,在子线程中通过handler的post(Runnable)方法更新UI信息。
图片描述

2)主线程创建handler,通过handler.postDelayed(myRunnable,1000)

图片描述
1、main中的handler.postDelayed(myRunnable,1000)是给ImageView设置Image,只执行一次

2、main中改成handler.post(myRunnable)也可以,直接加载Image,不会等待1000ms后再加载

3、MyRunnable中的handler.postDelayed(myRunnable,1000)是为了轮播图片,每隔1000ms后执行一次run方法,实现轮播

3)handler.sendMessage();

4)handler.sendEmptyMessage();

5)handler.removeCallback(runnable)

4、android 为什么要设计只能通过handler机制更新UI?

最根本的目的是解决多线程并发温问题:

假设如果在一个activity当中,有多个线程去更新UI,并且都没有加锁机制,那么会什么样子的问题?更新界面混乱。

如果对更新UI的操作都进行加锁处理的话又会产生什么样子的呢?性能下降。

出于对以上问题的考虑,Android给我们提供了一套更新UI的机制,我们只要遵循这个机制就可以了,根本不用去关心多线程并发的问题,所有的更新UI的操作,都是在主线程的消息队列中去轮训处理的。

5、handler的原理是什么?

一、Handler封装了消息的发送 (主要包括消息发送给谁)

Looper

1、内部包含一个消息对列,也就是MessageQueue,所有的handler发送的消息都走向这个消息对列。

2、Loopler.looper方法,就是一个死循环,不断地从MessageQueue取消息,如果有消息就处理消息,没有消息就阻塞

二、MessageQueue,就是一个消息对列,可以添加消息,并处理消息

三、handler也很简单,内部会跟Looper进行关联,也就是说在handler的内部可以找到Looper,找到Looper也就找到了MessageQueue,在handler中发送消息,其实就是向MessageQueue队列中发送消息

总结:handler负责发送消息,Looper负责接收handler发送的消息,并直接把消息回传给handler自己。MessageQueue就是一个存储消息的容器

7、如何实现一个与线程相关的Handler?

图片描述

打印的log日志如下:

图片描述

8、HandlerThread又是什么?

图片描述

当主线程handler中传入子线程的looper时,程序直接奔溃,报空指针错误,原因时存在多线程并发的问题,当两个线程在切换的时候,在程序运行到主线程中handler的创建时,传入了子线程的looper,而此时子线程中的looper还没有创建出来,所以会抛出空指针异常,那么这个问题怎么避免呢,就用到了HandlerThread。报错信息见下图:

图片描述

HandlerThread用法:

图片描述

通过HandlerThread的getLooper()方法可以很好地解决多线程并发产生的空指针异常的问题,日志打印如下:

图片描述

1)、HandlerThread的getLooper()源码:

图片描述

2)、HandlerThread的run()方法源码:
图片描述

通过两段源码可以发现,当mLooper为null时,wait等待,什么时候结束等待,唤醒呢?看HandlerThread的run()方法,先调用Looper.prepare(),然后通过Looper.myLooper()方法,把值给mLooper,再通过notifyAll()方法唤醒在等待的当前线程的对象,这时handler就能拿到looper对象,就不会再报空指针异常的问题。

9、如何在主线程给子线程发送消息呢?

图片描述
图片描述
图片描述

10、android中更新UI的几种方式?

(1)、runOnUiThread(runnable)

图片描述
图片描述

(2)、handler.post(runnable)

图片描述
图片描述
图片描述
(3)、handler.sendMessage

图片描述
图片描述

(4)、view.post(runnable)

图片描述
图片描述

11、非UI线程真的不能更新UI吗?

也是可以的,在onResum方法中checkThread前是可以在子线程中更新UI的,建议不要这样做

图片描述

12、使用handler时遇到的问题?

图片描述

(1)、子线程中更新UI

图片描述

(2)、子线程中创建handler

图片描述
图片描述

打开App,阅读手记
1人推荐
发表评论
随时随地看视频慕课网APP