Android Handler

1. handler

handler 是一个消息分发对象。handler 是android提供的用来更新UI和处理消息的机制。使用它最本质的原因是,为了解决多线程并发问题。所有更新UI的操作,都是在主线程的消息对列中轮询。
handler 将消息发给Looper管理的MessageQueue,并负责处理Looper分发给它的消息。

2. handler、Looper、Message三者关系

这3个都与异步消息处理有关。
异步消息处理线程启动之后,会进入一个无限的循环体中。每循环一次,从其内部的消息对列中取出一个消息,然后回调相应的消息处理函数,执行完一个消息后继续循环。若消息对列为空,线程则会阻塞等待。

android 消息机制主要是指Handler的运行机制,Handler运行需要MessageQueue和Looper支撑。MessageQueue采用的是单链表结构,Looper则是消息循环。由于MessageQueue只是一个消息存储单元,无法去处理消息,而Looper就是专门处理消息的,它会一直去循环查找是否有新消息,若有,则处理;若无,则等待。

Handler创建时会采用当前线程的Looper 来构造消息循环系统,线程默认是没有Looper的,若需要使用Handler,就必须为线程创建Looper,默认的UI线程ActivityThread,,它被创建的时候就会初始化Looper,因此在主线程中默认可以使用Handler。

3. 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):指定多少毫秒后发送消息。

Message: Handler 接收和处理的消息对象。其属性如下:
2个整型数值;
1个Object对象;
replyTo: 线程通信时使用;
what: 用户自定义消息码,让接收者识别消息。

MessageQueue:Message 的队列。采用先进先出管理Message,每个线程最多可以拥有一个。

Looper: 消息泵,MessageQueue的管理者,会不断地从MessageQueue中取出消息,并将消息分给对应的Handler处理。
每个线程只有一个Looper;
Looper.prepare() :为当前线程创建Looper对象;
Looper.myLooper():获取当前线程的Looper对象;
Handler:能把消息发送给MessageQueue,并负责处理Looper分给它的消息。

4. 如何发送消息

a. 使用Thread发送消息

在这里插入图片描述

b. 使用Runnable发送消息

在这里插入图片描述

5. 注意的点

非静态内部类容易引起内存泄漏:

  1. 当一个Android应用启动的时候,会自动创建一个供应用主线程使用的Looper实例。Looper的主要工作就是一个一个处理消息队列中的消息对象。在Android中,所有Android框架的事件(比如Activity的生命周期方法调用和按钮点击等)都是放入到消息中,然后加入到Looper要处理的消息队列中,由Looper负责一条一条地进行处理。主线程中的Looper生命周期和当前应用一样长。
  2. 当一个Handler在主线程进行了初始化之后,我们发送一个target为这个Handler的消息到Looper处理的消息队列时,实际上已经发送的消息已经包含了一个Handler实例的引用,只有这样Looper在处理到这条消息时才可以调用Handler#handleMessage(Message)完成消息的正确处理。
  3. 在Java中,非静态的内部类和匿名内部类都会隐式地持有其外部类的引用。静态的内部类不会持有外部类的引用。

解决的方式:
要解决这种问题,思路就是不适用非静态内部类,继承Handler时,要么是放在单独的类文件中,要么就是使用静态内部类。因为静态的内部类不会持有外部类的引用,所以不会导致外部类实例的内存泄露。当你需要在静态内部类中调用外部的Activity时,我们可以使用弱引用来处理。另外关于同样也需要将Runnable设置为静态的成员属性。注意:一个静态的匿名内部类实例不会持有外部类的引用。

摘自

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值