前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android Handler 机制简单讲解

Android Handler 机制简单讲解

作者头像
zinyan.com
发布2023-07-14 10:58:23
2140
发布2023-07-14 10:58:23
举报
文章被收录于专栏:zinyanzinyan

1. 前言

现在很多项目,可能Handler用的少了。但是如果你去面试,总是避免不了被问Handler原理等等。

下面将汇总介绍Handler的机制,从简单到复杂让大家都能一文就了解。下次被问到时可以有的放矢。

最简单的介绍,Handler就是一个用于处理多线程异步消息的机制。主要用于线程间通信。并不能支持进程间通信。

2. 正文

常见场景为:后台数据或IO线程获取信息,需要更新UI线程进行界面刷新。

而这两者之中的消息通讯,就可以通过Handler进行处理。

整个Handler 使用是由多个模块组合而成,分别分为:

  1. Message:代表需要传递的消息,每个消息都有自己的标签。
  2. MessageQueue :消息队列,通过一个单链表的数据结构来维护消息列表。
  3. Handler:消息入口和出口,负责向MessageQueue中发送消息(Handler.sendMessage()),同时也处理相应的消息事件(Handler.handleMessage()).
  4. Looper:消息分发者,负责不断循环执行Looper.loop将MessageQueue中的消息读取出来,分发给接收者进行处理Message。

2.1 Handler 原理

Android 中的Handler 通信是基于Linux系统的管道通信IPC机制来实现的线程通讯。

Looper.loop方法会不断循环处理Message,其中读取最终会通过JNI调用进入Native层,实现管道通讯。

3. 实例

我们在使用Handler中也有很多需要注意的地方。

3.1 Handler 内存泄漏

Handler 允许我们发送延时消息,但是如果在延时期间用户关闭了Activity,那么该Activity就会出现内存泄漏的问题。

主要是因为Message会持有Handler,而在Java中内部类会持有外部类,也就是Activity会被Handler持有。最终导致Activity无法被销毁,造成泄漏。

解决方法:将Handler定义为静态内部类,弱引用Activity。

实例:

代码语言:javascript
复制
public class DemoActivity extends AppCompatActivity{	
	private static class MyHandler extends Handler{		
        //弱引用持有HandlerActivity , GC 回收时会被回收掉
        private WeakReference<DemoActivity> weakReference;        public MyHandler(DemoActivity activity) {            this.weakReference = new WeakReference(activity);
        }        @Override
        public void handleMessage(Message msg) {            DemoActivity activity = weakReference.get();            super.handleMessage(msg);            if (null != activity) {                //执行业务逻辑
                Toast.makeText(activity,"handleMessage",Toast.LENGTH_SHORT).show();
            }
        }
	
}

3.2 Message 复用

获取 Message 大概有如下几种方式:

代码语言:javascript
复制
Message message1 = myHandler.obtainMessage(); 		   //通过 Handler 实例获取Message message2 = Message.obtain();   			  //通过 Message 获取Message message3 = new Message();  				 //直接创建新的 Message 实例

通过查看源码可知,Handler.obtainMessage() 方法也是调用了 Message.obtain() 方法。

为了节省开销,我们在使用的时候尽量复用 Message,使用前两种方式进行创建。

4. 问题汇总

1.Handler 能够更新UI线程。 2.一个线程可以有多个Handler,我们new Handler的时候并不是创建了线程,而是创建了一个接收者和发送者。 3.一个线程仅有一个Looper。 4.主线程创建的Handler 和子线程创建的Handler有什么区别? ActivityThread中的main已经针对Looper进行了prepar操作,我们只用直接创建Handler就可以了。 而在子线程中创建Handler需要我们调用Looper.prepare()进行初始化Looper,然后再调用Lppper.loop()让Looper进行循环运作下去。 5.Handler是如何确保线程安全的?因为Handler发送消息和取消消息都进行了synchronize修饰。 6.Handelr的消息延时准确么?并不准确,因为线程上的加锁操作,时间并不能完全准确。 7.Looper一直循环处理会不会导致应 用卡死? 在没有消息产生的时候,Looper会被阻塞(block),并进入休眠,一旦有消息添加,那么就会进行循环处理。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-07-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 zinyan 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 前言
  • 2. 正文
    • 2.1 Handler 原理
    • 3. 实例
      • 3.1 Handler 内存泄漏
        • 3.2 Message 复用
        • 4. 问题汇总
        相关产品与服务
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档