为什么在子线程中直接new Handler会报错?
来源:互联网 发布:淘宝免单群教程 编辑:程序博客网 时间:2024/04/28 06:10
为什么在子线程中直接new Handler会报错:
我们从报错开始追踪:“Can’t create handler inside thread that has not called Looper.prepare()”
—-》
错误日志就来自Handler的默认构造方法,源码如下:
/** * Default constructor associates this handler with the queue for the * current thread. * * If there isn't one, this handler won't be able to receive messages. */ public Handler() { 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) { //当mLooper为null时就会报这个异常 throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = null; }
—-》
那么我看下myLooper这个方法:
/** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static Looper myLooper() { return sThreadLocal.get(); }
很明显这里只是从sThreadLocal这个当前线程的对象身上获取到一个Looper。
—-》
那么我们需要知道这个Looper是什么时候被赋值到当前线程的对象上面的,Looper类中有一个prepare方法
/** Initialize the current thread as a looper. * This gives you a chance to create handlers that then reference * this looper, before actually starting the loop. Be sure to call * {@link #loop()} after calling this method, and end it by calling * {@link #quit()}. */ public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed));//在这里创建一个Looper对象并赋值给当前线程 }
—-》
那么这个Looper.prepare()方法是什么时候在哪里调用的呢?
当我们在主线程中创建Handler对象的时候没有问题,是因为主线程会自动调用Looper.prepare()方法去
给当前主线程创建并设置一个Looper对象,随意在Handler构造函数中从当前线程的对象身上拿到这个Looper。
但是子线程中并不会自动调用这个方法,所以要想在子线程中创建Handler对象就必须在创建之前手动调用Looper.prepare()方
法,否则就会报错。
1 0
- 为什么在子线程中直接new Handler会报错?
- Android 直接在子线程中创建Handler为什么会报错
- 如何在子线程中直接new Handler
- 子线程中能不能 new handler?为什么?
- 在子线程中new一个Handler
- 子线程新建Handler为什么会报错?——浅谈Handler、Looper、Message关系
- 子线程新建Handler为什么会报错?——浅谈Handler,Looper,Message之间的关系
- 在子线程中new Handler报错--Can't create handler inside thread that has not called Looper.prepare()
- 在子线程中new Handler报错--Can't create handler inside thread that has not called Looper.prepare()
- 在子线程中new Handler报错--Can't create handler inside thread that has not called Looper.prepare()
- 在Android子线程中初始化handler后,为什么该子线程也能更新UI?
- 如何在子线程中创建Handler?
- 在Android线程中设置控件的值会报错
- 在Android线程中设置控件的值会报错
- Handler消息传递机制(子线程中传递new Handler和主线程中new Handle传递消息)
- 为什么只能在主线程中操作UI?为什么子线程中setText不报错?
- 使用Handler在子线程中更新UI
- 使用Handler在子线程中更新UI
- CodeForces 353A Domino(水。。)
- 例题7-1 除法UVa 725
- 在Linux 6上使用UDEV解决RAC ASM存储设备名问题
- [LeetCode] Plus One
- Linux下使用fstatfs/statfs查询系统相关信息
- 为什么在子线程中直接new Handler会报错?
- 一、计算机网络——基本概念
- HDU 5410 CRB and His Birthday
- Swift 中数组和链表的性能
- CodeForces 276E Little Girl and Problem on Trees(线段树区间更新)
- 线性表之顺序表
- Android-Volley网络通信框架(二次封装数据请求和图片请求(包括处理请求队列和图片缓存))
- ViewPager内嵌ViewPager以及与SwipeRefreshLayout冲突的问题
- 最长上升子序列nlogn算法