Android-Daily-Interview
Android-Daily-Interview copied to clipboard
2019-07-09:为什么在子线程中创建Handler会抛异常?
因为没有looper,需要先prepare
不能在还没有调用 Looper.prepare() 方法的线程中创建 Handler。
因为抛出异常的地方,在 mLooper 对象为null的时候, 会抛出异常。说明这里的Looper.myLooper();的返回值是 null。 只有调用了Looper.prepare()方法,才会构造一个Looper对象并在 ThreadLocal 存储当前线程的 Looper 对象。
这样在调用 Looper.myLooper() 时,获取的结果就不会为 null。
链接:Handler的工作原理,为什么在子线程中执行 new Handler() 会抛出异常?
要创建Handler必须有looper,先运行looper.prepare
楼上说的正解,主线程默认执行了looper.prepare方法,此时使用Handler就可以往相信队列中不断进行发送消息和取出消息处理,反之没有执行looper.prepare方法,就会抛出异常,这个在源码中有所体现
所以个人感觉这么提问不是很合理,应该问为什么在子线程中不能直接创建Handler来使用?然后引出主线程默认调用looper.prepare这个会合理一点 个人意见
我是小黑 @Moosphan 沐风大佬
Handler 的构造方法中,会通过Looper.myLooper()获取looper对象,如果为空,则抛出异常,主线程则因为已在入口处ActivityThread的main方法中通过 Looper.prepareMainLooper()获取到这个对象,并通过 Looper.loop()开启循环,在子线程中若要使用handler,可先通过Loop.prepare获取到looper对象,并使用Looper.loop()开启循环。
在子线程中创建handler需要手动创建looper。
亲测 ,在华为 Android p8 Android 8.0 下 子线程 创建 Handler 不会闪退。预估华为做了修改,下次回答:可能在 国内一些手机不会闪退。
楼上的都没有回答到点上 子线程创建Handler会抛出异常的原因是因为在looper里面ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>() ThreadLocal 就是为了保存的Looper只能在指定线程中获取Looper 因为子线程创建new Handler()并没有指定Looper 所以它就去获取ActivityThread的main方法中创建的looper 而此时的这个looper 是受线程保护的 所以子线程是无法获取的 因此抛出异常所以在子线程中没有looper 如果需要在子线程中开启handle要手动创建looper