Android Handler通信

一  Android中使用Handler场景

      在开发中更新我们刷新视图都需要在主线程中更新,子线程是不支持更新视图操作的。所以当我们做一些耗时操作的时候可以不能马上得到反馈刷新UI,比如下载文件或者下载图片这些操作都比较耗时,我们一般会重新创建一个子线程异步处理耗时操作,这样就不会堵塞主线程导致卡顿的情况。这个时候Handler就起到了作用。我们可以用Handler Looper MessageQueue这套异步消息处理机制来处理这种情况,线程中发送消息通知,主线程来处理消息刷新视图。 

     Handler使用的生产消费者设计模式

生产消费者模式就是类似于生活中寄快递一样,寄东西的人可以视为生产者,而快递员就是消息缓存区、快递员负责全部快递的维护和派发、只要有还有快递快递员就是一直送到没有为止,收件人就是消费者负责接收快递员的快件。可以看到整个过程发件人不需要关心收件人的具体情况,只需要把收件人的地址写对就行。而快递员也不需要关心发件人和收件人的信息,快递员只负责收快递按快递地址送到到收件人手里。收件人只需要等待快递的送达就好了。 

优点

  • 低耦合
    为什么不直接让消费者调用生产者的某个方法?如果这样直接调用必然会产生相互依赖的情况也就是耦合,如果以后生产者和消费者某一方变化都有可能会影响到对方,但是如果二者直接不直接依赖而是通过缓冲区来交互,这样耦合性就大大减低了。

  • 支持并发
    生产者可以放心的产生数据直接扔给消息缓冲区,而不用等待消费者那边是否已经处理完了消息,而导致生产者等待状态(生产者消息堵塞),这样就可以不用依赖消费者的处理速度了,互相独立。

  • 自由发挥
    这种模式还有一好处就是,如果生产者生产的数据速度过快,而消费者那边处理的比较慢,那么这个时候消息都会存在于缓冲区。这样生产者就能慢慢的消费这些数据了,所以定为自由发挥。

Handler Looper MessageQueue 的职责

MessageQueue 就是设计模式中的缓冲区,它负责接收生产者发送过来的数据先进先出的队列形式,保存着所有消息。在UI Thread中通过looper 不断从MessageQueue 取出消息在执行任务。

Looper 的主要工作就是维护MessageQueque中的消息队列,它负责从MessageQueue中取出要执行的消息任务,先判断Looper是否为null,不为null就循环状态不断从MessageQueue中取出消息,然后通过dispatchMessage派发出去就行处理。

每个线程只能有一个Looper对象,而且是通过ThreadLocal来存放,其他线程无法访问当前的Looper。

每个application都默认拥有一个Looper对象注释可以看到。Framework会通过JNI调用如下二个方法创建一个MainLooper,所以说UI线程默认就有一个Looper对象,可通过Looper.myLooper()方法获取到。

常用的方法 prepare()创建一个looper对象,在其他线程中想具有消息循环功能这个方法就必须调

Handler 是负责把Message压入Queue中,还负责处理Message。Handler工作必须依赖Looper才行,没有Looper对象会抛出RuntimeException异常,不管是post sendMessage 还是延时的消息发送,最终都会到enqueueMessage方法中把消息传到缓冲区等待Looper处理。

 

Handler导致的内存泄漏问题

下面这段代码是一个内部类,在Java中内部类或者匿名内部类都会隐私的持有外部类对象,而在Android中使用Handler的一般都是Activity,这就导致如果handler还在执行中而actiivty finsh掉,activity就不能被正常销毁回收。进而GC的时候就导致JVM不能回收Activity,有可能多次操作后就OOM了。

解决办法
1.把内部类换成static, static不会隐式持有外部对象。

由于Handler不再持有外部类对象的引用,导致程序不允许你在Handler中操作Activity中的对象了。所以你需要在Handler中增加一个对Activity的弱引用

2.一般Handler导致的内存泄漏都是因为,消息处理是异步的。finsh的时候消息还在处理等待状态,这个时候可以在activity finsh的时候把handler移除掉,调用removeCallbacks方法移除。
3.关闭Activity的时候停掉你的后台线程。

总结

Handler 消息处理和发送的角色, 主要有二个作用 1.发送消息 2.处理消息
Looper 消息轮循器 looper方法里面是一个死循环,它不断从MessageQueue中取出消息,直到为null为止。
MessageQueue 消息队列 保存着全部消息的一个队列

在其他线程中使用Looper,一个Looper对象可以有多个Handler对象。

作者:金威JW
链接:https://www.jianshu.com/p/7bdb6f977ab7
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值