【第八关】Android Handler详解
参考:https://www.jianshu.com/p/9fe944ee02f7
https://www.jianshu.com/p/69b550cb7d43
https://www.jianshu.com/p/3855e0aa7900
Handler是什么
- Handler是一个消息分发对象。handler是Android给我们提供用来更新UI的一套机制,也是一套消息处理机制,我们可以发消息,也可以通过它处理消息。简单定义为一套Android消息传递机制
- 1:To schedule messages and runnables to be executed as some point in the future 定时任务
2:To enqueue an action to be performed on a different thread than your own 在不同线程中执行任务
Handler作用
在多线程的应用场景中,将工作线程中需要跟新UI的操作信息传递到UI主线程,从而实现工作线程对UI的更新处理,最终事项异步消息的处理
为什么要使用Handler?
- 最根本的目的就是为了解决多线程并发的问题(多个线程并发更新UI的同时,保证线程安全),将工作线程需操作UI的消息传递到主线程,使得主线程可根据工作线程的需求更新UI,从而避免线程操作不安全的问题
- 打个比方,如果在一个activity中有多个线程,并且没有加锁,就会出现界面错乱的问题。但是如果对这些更新UI的操作都加锁处理,又会导致性能下降。处于对性能的问题考虑,Android给我们提供这一套更新UI的机制我们只需要遵循这种机制就行了。不用再去关系多线程的问题,所有的更新UI的操作,都是在主线程的消息队列中去轮询的。
- 它把消息发送给Looper管理的MessageQueue,并负责处理Looper分发给他的消息
相关概念
- Handler类包含如下方法用于发送,处理消息
- void handleMessage(Message msg):处理消息的方法。通常用于被重写
- final boolean hasMessages(int what):检查消息队列中是否包含what属性为指定值的消息。
- final boolean hasMessages(int what, Object object):检查消息队列中是否包含what属性为指定值且object属性为指定对象的消息。
- 多个重载的Message obtainMessage():获取消息。
- sendEmptyMessage(int what):发送空消息。
- final boolean sendEmptyMessageDelayed(int what, long delayMillis):指定多少毫秒后发送空消息。
- final boolean sendMessage(Message msg):立即发送消息。
- final boolean sendMessageDelayed(Message msg, long delayMillis):指定多少毫秒后发送消息。((经验证,该时间为活动onResume时到handleMessage之间的时间))
- Message:Handler接收和处理的消息对象
- 2个整型数值(arg1,arg2):轻量级存储int类型的数据
- 1个Object:任意对象
- replyTo:线程通信时使用
- what:用户自定义的消息码,让接收者识别消息
- MessageQueue:Message队列
- 采用先进先出 的方式管理Message
- 每一个线程最多可以拥有一个
- Looper:消息泵,是MessageQueue的管理者,会不断从MessageQueue中取出消息,并将消息分给对应的Handler处理
- 每个线程只有一个Looper
- Looper.prepare():为当前线程创建Looper对象
- Looper.myLooper():可以获得当前线程的Looper对象
- Handler:能把消息发送给MessageQueue,并负责处理Looper分给它的消息
核心类
Handler机制中有3个重要的类:
- 处理器类(Handler)
- 消息队列类(MessageQueue)
- 循环器类(Looper)
类图:
具体介绍:
工作原理
Handler
机制得到工作流程主要包括4个步骤:
- 异步通信准备
- 消息发送
- 消息循环
- 消息处理
- 具体如下图:
- 工作流程图
- 异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次,从其内部的消息队列中取出一个消息,然后回调相应的消息处理函数,执行完成一个消息后则继续循环。若消息队列为空,线程则会阻塞等待。
- Android消息处理机制主要是指Handler的运行机制,Handler运行需要底层的MessageQueue和Looper支撑。其中MessageQueue采用的是单链表的结构(先进先出),Looper可以叫做消息循环。由于MessageQueue只是一个消息存储单元,不能去处理消息,而Looper就是专门来处理消息的,Looper会已无限循环的形式去查找是否有新消息,如果有的话,就处理,否则就线程阻塞,等待着。
- Handler创建的时候会采用当前线程的Looper来构造消息循环系统, 注:线程默认是没有Looper的,如果需要使用Handler就必须为线程创建Looper,因为默认的UI主线程,也就是ActivityThread,ActivityThread被创建的时候就会初始化Looper,这也是在主线程中默认可以使用Handler的原因。
- 示意图
- 注意
线程(Thread),循环(Looper),处理者(Handler)之间的对应关系如下:- 1个线程(Thread)只能绑定1个循环器(Looper),但可以由多个处理器(Handler)
- 1个循环器(Looper)可绑定多个处理者(Handler)
- 1个处理者(Looper)只能绑定1个循环器(Looper)
使用步骤
- 方式1:使用Handler.sendMessage()
在该使用方式中,又分为两种:新建Handler子类(内部类),匿名Handler子类,但本质相同,即继承了Handler类&创建了子类/** * 方式1:新建Handler子类(内部类) */ // 步骤1:自定义Handler子类(继承Handler类) & 复写handleMessage()方法 class mHandler extends Handler { // 通过复写handlerMessage() 从而确定更新UI的操作 @Override public void handleMessage(Message msg) { ...// 需执行的UI操作 } } // 步骤2:在主线程中创建Handler实例 private Handler mhandler = new mHandler(); // 步骤3:创建所需的消息对象 Message msg = Message.obtain(); // 实例化消息对象 msg.what = 1; // 消息标识 msg.obj = "AA"; // 消息内容存放 // 步骤4:在工作线程中 通过Handler发送消息到消息队列中 // 可通过sendMessage() / post() // 多线程可采用AsyncTask、继承Thread类、实现Runnable mHandler.sendMessage(msg); // 步骤5:开启工作线程(同时启动了Handler) // 多线程可采用AsyncTask、继承Thread类、实现Runnable /* *方式2:新建匿名内部类 */ // 步骤1:在主线程中 通过匿名内部类 创建Handler类对象 private Handler mhandler = new Handler(){ // 通过复写handlerMessage()从而确定更新UI的操作 @Override public void handleMessage(Message msg) { ...// 需执行的UI操作 } }; // 步骤2:创建消息对象 Message msg = Message.obtain();