Handler详解


主线程和子线程

从用途上来说Android的线程主要分为主线程和子线程两类,主线程主要处理和界面相关的工作,子线程主要处理耗时操作。除Thread之外,Android中还有其他扮演线程的角色如AsyncTask、IntentService、HandlerThread,其中AsyncTask的底层用到了线程池,IntentService和HandlerThread的底层直接使用了线程。

AsyncTask内部封装了线程池和Handler主要是为了方便开发者在在线程中更新UI;HandlerThread是一个具有消息循环的线程,它的内部可以使用Handler;IntentService是一个服务,系统对其进行了封装使其可以更方便的执行后台任务,IntentService内部采用HandlerThread来执行任务,当任务执行完毕后IntentService会自动退出。IntentService是一个服务但是它不容易被系统杀死因此它可以尽量的保证任务的执行。

主线程是指进程所拥有的的线程,在Java中默认情况下一个进程只能有一个线程,这个线程就是主线程。主线程主要处理界面交互的相关逻辑,因为界面随时都有可能更新因此在主线程不能做耗时操作,否则界面就会出现卡顿的现象。主线程之外的线程都是子线程,也叫做工作线程。

Android沿用了Java的线程模型,也有主线程和子线程之分,主线程主要工作是运行四大组件及处理他们和用户的交互,子线程的主要工作就是处理耗时任务,例如网络请求,I/O操作等。Android3.0开始系统要求网络访问必须在子线程中进行否则就会报错,NetWorkOnMainThreadException。

消息机制

Android的消息机制就是 handler的运行机制

作用

1、调度计划执行的消息或任务
2、在子线程上进行任务排队

原理

在这里插入图片描述

Message Queue(消息队列):用来存放通过Handler发布的消息,通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列
Handler:可以发布或者处理一个消息或者操作一个Runnable,通过Handler发布消息,消息将只会发送到与它关联的消息队列,然也只能处理该消息队列中的消息
Looper:是Handler和消息队列之间通讯桥梁,程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的Handler,Handler接受到消息后调用handleMessage进行处理。
Message:消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理

常用方法

  • 发送消息
// 发送一个消息
mHandler.sendMessage(Message msg);

// 发送一个延迟的消息标识
mHandler.sendEmptyMessageDelayed(int what, long delayMillis);
  • 处理消息
 @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            NowPlayingActivity activity = mActivty.get();
            if (activity != null) {
                switch (msg.what) {
                    case MSG_FAST_FORWARD:
                        activity.fastForward();
                        break;
                    case MSG_BACK_FORWARD:
                        activity.backForward();
                        break;
                }
            }
        }
  • 发送一个runnable
mHandler.post(runnable);
  • 获取,移除消息等

内存泄露

handler使用不当会导致内存泄漏问题

handler内部类持有activity会导致内存泄漏,采用静态内部类并使用弱引用持有activity ,在退出的时候remove掉handler

 private static class MyHandler extends Handler {
        private final WeakReference<NowPlayingActivity> mActivty;

        private MyHandler(NowPlayingActivity mActivty) {
            //当前Activity的弱引用
            this.mActivty = new WeakReference(mActivty);
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            NowPlayingActivity activity = mActivty.get();
            if (activity != null) {
                switch (msg.what) {
                    case MSG_FAST_FORWARD:
                        activity.fastForward();
                        break;
                    case MSG_BACK_FORWARD:
                        activity.backForward();
                        break;
                }

            }
        }
    }

HandlerThread

在这里插入图片描述

含义

HandlerThread是Thread的子类,自带一个looper,可以通过looper创建一个handler。HandlerThread是系统封装好的自带looper的线程,在子线程中无需在手动去调用Looper.prepare()和Looper.loop()这些方法。

可以封装一个HandlerThread的工具类

private static void init() {
        if (sThread == null
                || sThread.isInterrupted()
                || sThread.getState() == State.TERMINATED) {
            synchronized (MSGHandlerThread.class) {
                sThread = new MSGHandlerThread("MSG_HT_CC");
                sThread.start();
                sHandler = new Handler(sThread.getLooper());
            }
        }
    }

线程池

多线程并且调用频繁的场景建议使用线程池,线程池相关的介绍 JAVA线程池详解

参考链接

  1. handler机制详解
  2. 关于handler,看这篇就够了
  • 11
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值