Handler机制浅析

本文详细解析了Android中的Handler机制,从创建Handler、发送消息到接收消息的过程,涉及Message、MessageQueue、Looper的角色与职责,并通过源码分析解释了为何必须调用Looper.prepare()和Looper.loop()。通过实例展示了Handler发送和接收消息的工作原理,以及消息队列的管理方式。
摘要由CSDN通过智能技术生成

使用方法

实例化一个handler对象

val handler = object : Handler() {
            override fun handleMessage(msg: Message) {
                Log.e(TAG, "收到消息:" + msg.obj.toString())
                super.handleMessage(msg)
            }
        }

在需要发送消息的地方这样调用

val msg = Message()
msg.obj = "一条消息"
handler.sendMessage(msg)

打印日志

 我们一般是在主线程创建handler,子线程发消息,比如我们可以这样写

object : Thread() {
            override fun run() {
                super.run()
                val msg = Message()
                msg.obj = "子线程消息"
                handler.sendMessage(msg)
            }
        }.start()

打印日志

 有时候可能需要在子线程创建handler,主线程发消息,我们可能会这样写

class HandlerTestActivity : AppCompatActivity() {
    val TAG = "HandlerTestActivity"

    var handler:Handler?=null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_handler_test)
        object : Thread() {
            override fun run() {
                super.run()
                Looper.prepare()
                handler = object : Handler() {
                    override fun handleMessage(msg: Message) {
                        Log.e(TAG, "收到消息:" + msg.obj.toString())
                        super.handleMessage(msg)
                    }
                }
                Looper.loop()
            }
        }.start()

    }
    //按钮点击事件,点击后发送消息
    fun sendMessage(view: View) {
        val msg = Message()
        msg.obj = "主线程消息"
        handler?.sendMessage(msg)
    }
}

运行代码后,点击按钮会得到如下报错

 我们根据报错信息,到源码中寻找报错的原因,发现在Handler的构造方法中,有这个报错信息的代码

  public Handler(@Nullable Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            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());
            }
        }

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

可以看出,当mLooper为null时,就会抛出这个错误,mLooper是通过Looper.myLooper()获取的,

我们找到Looper.myLooper()方法

public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

发现是调用了sThreadLocal的get()方法获取的,而sThreadLocal是一个ThreadLocal对象,持有Looper的范型

 @UnsupportedAppUsage
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

他的get方法是这样的

public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

简单点说,就是从一个Map里取出一个T对象,也就是上面的范型Looper

有get就有set,set方法是这样的

public void set(T value) {
        Thread
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值