Android消息机制之Handler 详解

本文详细探讨了Android中的Handler消息机制,从Handler的构造方法、Looper的工作原理、消息的存储与取出流程等方面进行深入剖析,揭示了Handler如何连接主线程和子线程。同时,文章还介绍了Handler可能导致内存泄漏的情况及解决方案,以及主线程Looper的特点。
摘要由CSDN通过智能技术生成

简介

作为一个Android开发者,Handler的大名你一定听过。做Android开发肯定离不开Handler,它通常被我们用来连通主线程和子线程。

可以说只要有异步的地方一定有Handler。

那么,你了解过为什么Handler能连通主线程和子线程吗,也就是说,你了解过Handler背后的原理吗?

就让本文带你了解。

Handler的基本用法

按照惯例,我们首先看下Handler的一般用法:

Handler mHandler = new Handler() {
   
    @Override
    public void handleMessage(final Message msg) {
   
        // 在这里接受并处理消息
    }
};

//发送消息
mHandler.sendMessage(message);
mHandler.post(runnable);

也就是创建一个Handler对象,并重写handlerMessage方法,然后在需要的时候调用sendMessage方法传入一个message对象,或者调用post方法传入一个runnable对象。

那么我们从他的构造方法开始看起吧。

从Handler构造方法入手

public Handler() {
   
    // ->> 分析1.1
    this(null, false);
}

分析1.1 Handler # 构造方法

/**
 * 分析1.1:实际上调用的又是另一个构造方法
 */
public Handler(@Nullable Callback callback, boolean async) {
   
    if (FIND_POTENTIAL_LEAKS) {
   
        // 这个变量字面意思是找到内存泄漏,
        // 但是整个Handler中除了这块以及定义这个变量为false之外,
        // 就没有其他地方使用到过这个变量了,所以这块我也不太懂这个变量是怎么变为true的
        final Class<? extends Handler> klass = getClass();
        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                (klass.getModifiers() & Modifier.STATIC) == 0) {
   
            Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                klass.getCanonicalName());
        }
    }

    // ->> 分析1.2
    mLooper = Looper.myLooper();
    // ->> 分析1.3
    if (mLooper == null) {
   
        throw new RuntimeException(
            "Can't create handler inside thread " + Thread.currentThread()
                    + " that has not called Looper.prepare()");
    }
    // 获取对象的mQueue属性,mQueue就是MessageQueue
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

分析1.2 Looper # myLooper()

/**
 * 分析1.2:Looper.myLopper()
 * 实际上调用的是ThreadLocal的get方法,然后返回该线程的Looper对象
 */
public static @Nullable Looper myLooper() {
   
    return sThreadLocal.get();
}

ThreadLocal是一个数据存储类,他的特别之处在于他是线程间独立的,也就是说这个线程放入到ThreadLocal的数据,其它线程是获取不到的。sThreadLocal就是获取当前线程的Looper对象。详细可见我之前的博客。

分析1.3 Looper # prepare()

为什么说如果mLooper为空就抛异常呢,这是因为一个Handler必须和一个Looper绑定,并且要先初始化Looper才能去初始化Handler。初始化Looper就通过Looper的prepare方法。

/**
 * 分析1.3:Looper.prepare()
 */
public static void prepare() {
   
    prepare(true);
}

private static void prepare(boolean quitAllowed) {
   
    if (sThreadLocal.get() != null
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值