加入收藏 | 设为首页 | 会员中心 | 我要投稿 济南站长网 (https://www.0531zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

Handler的相关知识和实施

发布时间:2021-11-24 19:10:24 所属栏目:教程 来源:互联网
导读:最近我在网路上查了很多关于handler的知识,但是感觉总是觉得有很多问题?? 1.为什么要使用handler? 2.handler是异步的,创建一个handler实例是创建一个新的线程吗??(NO,没有创建新的线程,但是为什么没有阻塞主线程?这是有系统管理Looper的) 3.在同

最近我在网路上查了很多关于handler的知识,但是感觉总是觉得有很多问题??
 
1.为什么要使用handler?
 
2.handler是异步的,创建一个handler实例是创建一个新的线程吗??(NO,没有创建新的线程,但是为什么没有阻塞主线程?这是有系统管理Looper的)
 
3.在同一线程中,handler1发送消息,handler1能收到消息,handler2能收到吗?
 
4.在子线程中,运用主线程中定义的handler,sendMessage,主线程中得handler能收到吗?
 
5.在子线程中创建一个handler实例,并发送消息,这样可以吗???
 
6.HandlerThread是什么,什么时候使用??
 
7.Message,Looper,Handler,MessageQueue等地关系如何???
 
8.sendMessage和post的区别是什么??是否共用一个消息队列messageQueue??
 
9.handler是再主线程内吗?(不一定,一般是的,但是如果在handler的构造函数中传入子线程的Looper,则就会在该线程中)
 
10.子线程中构造的的handler可以传入主线程的Looper,就是操控主线程的消息队列??(可以)
 
带着问题去学习handler,我想应该会很有意思的。下面就是来解决这些问题的,(*^__^*) 嘻嘻……
 
先介绍下handler的基本知识
 
Handler
 
Handler在Android里负责发送和处理消息。它的主要用途:
  1)按计划发送消息或执行某个Runnanble(使用POST方法),类似定时器;
  2)从其他线程中发送来的消息放入消息队列中,避免线程冲突(常见于更新UI线程);
   默认情况下,Handler接受的是当前线程下的消息循环实例(使用Handler(Looper looper)、Handler(Looper looper, Handler.Callback callback)可以指定线程),同时一个消息队列可以被当前线程中的多个对象进行分发、处理(在UI线程中,系统已经有一个Activity来处理了,你可以再起若干个Handler来处理)。在实例化Handler的时候,Looper可以是任意线程的,只要有Handler的指针,任何线程也都可以sendMessage。Handler对于Message的处理不是并发的。一个Looper 只有处理完一条Message才会读取下一条,所以消息的处理是阻塞形式的(handleMessage()方法里不应该有耗时操作,可以将耗时操作放在其他线程执行,操作完后发送Message(通过sendMessges方法),然后由handleMessage()更新UI)。
 
 
 
Looper
 
Looper类用来创建消息队列. 每个线程最多只能有一个消息队列, android中UI线程默认具有消息队列, 但非UI线程在默认情况下是不具备消息队列的. 如果需要在非UI线程中开启消息队列, 需要调用Looper.prepare()方法, 在该方法的执行过程中会创建一个Looper对象, 而Looper的构造函数中会创建一个MessageQueue instance(Looper的构造函数是私有的, 在Looper类之外无法创建其对象). 此后再为该线程绑定一个Handler instance, 然后调用Looper.loop()方法, 就可以不断的从消息队列中取出消息和处理消息了. Looper.myLoop()方法可以得到线程的Looper对象, 如果为null, 说明此时该线程尚未开启消息队列.
 
创建一个 Looper 对象时,会同时创建一个 MessageQueue 对象(一个looper对应一个MessageQueue)。除了主线程有默认的 Looper ,其他线程默认是没有 MessageQueue 对象的,所以,不能接受 Message 。如需要接受,自己定义 一个 Looper 对象 ( 通过 prepare 函数 ), 这样该线程就有了自己的 Looper 对象和 MessageQueue 数据结构了。  
Looper 从 MessageQueue 中取出 Message 然后,交由 Handler 的 handleMessage 进行处理。处理完成后,调用 Message.recycle() 将其放入 Message Pool 中。
 
Message
 
Message :消息对象, Message Queue 中的存放的对象。一个 Message Queue 中包含多个 Message 。 Message 实例对象的取得,通常使用 Message 类里的静态方法 obtain(), 该方法有多个重载版本可供选择;它的创建并不一定是直接创建一个新的实例,而是先从 Message Pool( 消息池 ) 中看有没有可用的 Message 实例,存在则直接取出返回这个实例。如果 Message Pool 中没有可用的 Message 实例,则才用给定的参数创建一个 Message 对象。调用 removeMessages() 时,将 Message 从 Message Queue 中删除,同时放入到 Message Pool 中。除了上面这种方式,也可以通过 Handler 对象的 obtainMessage() 获取 一个 Message 实例。
 
Message类用于表示消息. Message对象可以通过arg1, arg2, obj字段和setData()携带数据, 此外还具有很多字段.
 
when字段决定Message应该何时出对处理,;
 
target字段用来表示将由哪个Handler对象处理这个消息;
 
next字段表示在消息队列中排在这个Message之后的下一个Message;
 
callback字段如果不为null表示这个Message包装了一个runnable对象;
 
what字段表示code, 即这个消息具体是什么类型的消息. 每个what都在其handler的namespace中, 我们只需要确保将由同一个handler处理的消息的what属性不重复就可以.
 
MessageQueue
 
MessageQueue类用于表示消息队列. 队列中的每一个Message都有一个when字段, 这个字段用来决定Message应该何时出对处理. 消息队列中的每一个Message根据when字段的大小由小到大排列, 排在最前面的消息会首先得到处理, 因此可以说消息队列并不是一个严格的先进先出的队列。  主线程创建时,会创建一个默认的 Looper 对象,而 Looper 对象的创建,将自动创建一个 Message Queue 。其他非主线程,不会自动创建 Looper ,要需要的时候,通过调用 prepare 函数来实现。
 
将消息压入消息队列:
 
Message对象的target字段关联了哪个线程的消息队列, 这个消息就会被压入哪个线程的消息队列中.
 
a 调用Handler类中以send开头的方法可以将Message对象压入消息队列中,;
 
调用Handler类中以post开头的方法可以将一个runnable对象包装在一个Message对象中, 然后再压入消息队列, 此时入队的Message其callback字段不为null, 值就是这个runnable对象. 调用Handler对象的这些方法入队的Message, 其target属性会被赋值为这个handler对象.
 
b. 调用Message对象的sendToTarget()方法可以将其本身压入与其target字段(即handler对象)所关联的消息队列中.
 
从消息队列中取出消息并处理消息:
 
所有在消息队列中的消息, 都具有target字段. 消息是在target所关联的线程上被取出和处理的.
 
1. 如果取出的Message对象的callback字段不为null, 那么就调用callback字段的run()方法(callback字段的类型是runnable). 注意此时并不开启一个新的线程运行run()方法, 而是直接在handler对象(即Message的target字段)所关联的线程上运行.
 
2. 如果取出的Message对象的callback字段为null, 且Handler对象中的callback字段也为null, 那么这个消息将由Handler对象的handleMessage(msg)方法处理. 注意Message对象的callback字段是Runnable类型的而Handler对象的callback字段是Callback类型的, Handler对象的callback字段是在创建Handler instance的时候指定的, 如果没有指定则这个字段为null, 详见Handler类的四个构造方法.
 
3. 如果取出的Message对象的callback字段为null, 且Handler对象中的callback字段不为null, 那么这个消息将由Handler对象中的callback字段的handleMessage方法处理.

(编辑:济南站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读