Only one Looper may be created per thread
2015-11-27 15:14
465 查看
在开发一套智能家居的APP时,因为要让APP自动根据用户操作过的数据来更新自己的状态。
出现大致一个这样的代码结构(该结构不是原项目中的,这是随便写了一个与项目代码结构一致):
class LoopThread extends Thread {
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
Looper.prepare();
postt(100);
Log.e("sos", "Looper 【外面的】 Log");
Looper.loop()
}
}
public void postt(int tmp) {
while (true) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Log.e("sos", "【外面的】 Log"+tmp );
}
}, 1000);
tmp++;
}
}因为线程中调用了Handler,不加Looper会报RuntimeException:Can't create handler inside thread that has not called Looper.prepare()
原因究其 Android 系统的消息队列和消息循环都是针对具体线程的,一个线程可以存在(当然也可以不存在)一个消息队列和一个消息循环(Looper),
特定线程的消息只能分发给本线程,不能进行跨线程,跨进程通讯。但是创建的工作线程默认是没有消息循环和消息队列的,如果想让该线程具有消息队
列和消息循环,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。
所以:先调用Looper.prepare();获取Looper对象;然后再Looper.loop()循环起来;注意,因为Looper.prepare()和Looper.loop()后面的代码是不会被执行的,
所以Looper.prepare()和Looper.loop()包裹哪些代码得需要根据自己代码情况;
然后代码为:
···
Looper.prepare();
postt(100);
Log.e("sos", "Looper 【外面的】 Log");
Looper.loop()
···然后又又报错:NullPointExceptio,一直指向Looper.loop()出错。我怀疑其是Looper为空,但是Looper是系统提供的类;测试中发现我的APP第一次运行正常,第二次运行的时候才开始报错的;
究其原因:可能是我项目中一系列复杂操作导致的吧;因为我的项目时再service中通过内容提供者操作数据库,然后通过内容观察者监听数据库中数据变化,去执行了一个接口回调;
网上找了各种资料也没有找到答案。搞了一大半天都没解决;看了好几遍Handler和Looper机制的原理;后来觉得应该是内容监听者第二次响应时又再次执行了Looper.loop(),导致其为空的;
想着不如这样尝试:因为我监听了数据库中的数据变化,一段有变化就会执行这个死循环一次,每次执行结束后我就停止Looper;第二次再监听到数据有变化执行时再次重新调用Looper.prepare()获取其对象;
于是解决了问题,很欣慰!
后来的解决方案:
异常:RuntimeException: Unable to start ···
···java.lang.RuntimeException: Only one Looper may be created per thread
每一个线程中只需创建一个消息泵(Looper);
是因为线程下又开有线程。
出现大致一个这样的代码结构(该结构不是原项目中的,这是随便写了一个与项目代码结构一致):
class LoopThread extends Thread {
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
Looper.prepare();
postt(100);
Log.e("sos", "Looper 【外面的】 Log");
Looper.loop()
}
}
public void postt(int tmp) {
while (true) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Log.e("sos", "【外面的】 Log"+tmp );
}
}, 1000);
tmp++;
}
}因为线程中调用了Handler,不加Looper会报RuntimeException:Can't create handler inside thread that has not called Looper.prepare()
原因究其 Android 系统的消息队列和消息循环都是针对具体线程的,一个线程可以存在(当然也可以不存在)一个消息队列和一个消息循环(Looper),
特定线程的消息只能分发给本线程,不能进行跨线程,跨进程通讯。但是创建的工作线程默认是没有消息循环和消息队列的,如果想让该线程具有消息队
列和消息循环,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。
所以:先调用Looper.prepare();获取Looper对象;然后再Looper.loop()循环起来;注意,因为Looper.prepare()和Looper.loop()后面的代码是不会被执行的,
所以Looper.prepare()和Looper.loop()包裹哪些代码得需要根据自己代码情况;
然后代码为:
···
Looper.prepare();
postt(100);
Log.e("sos", "Looper 【外面的】 Log");
Looper.loop()
···然后又又报错:NullPointExceptio,一直指向Looper.loop()出错。我怀疑其是Looper为空,但是Looper是系统提供的类;测试中发现我的APP第一次运行正常,第二次运行的时候才开始报错的;
究其原因:可能是我项目中一系列复杂操作导致的吧;因为我的项目时再service中通过内容提供者操作数据库,然后通过内容观察者监听数据库中数据变化,去执行了一个接口回调;
网上找了各种资料也没有找到答案。搞了一大半天都没解决;看了好几遍Handler和Looper机制的原理;后来觉得应该是内容监听者第二次响应时又再次执行了Looper.loop(),导致其为空的;
想着不如这样尝试:因为我监听了数据库中的数据变化,一段有变化就会执行这个死循环一次,每次执行结束后我就停止Looper;第二次再监听到数据有变化执行时再次重新调用Looper.prepare()获取其对象;
于是解决了问题,很欣慰!
后来的解决方案:
··· Looper.prepare(); Looper mLooper = Looper.myLooper(); update((int) switchs.getId(), switchs.getStatus()); mLooper.quit();//停止循环,下次执行的时候重新进入Looper消息泵中 Looper.loop(); ···
异常:RuntimeException: Unable to start ···
···java.lang.RuntimeException: Only one Looper may be created per thread
每一个线程中只需创建一个消息泵(Looper);
是因为线程下又开有线程。
相关文章推荐
- 用CSS让表格返转的代码 IE only
- 解析jQuery的三种bind/One/Live事件绑定使用方法
- mysql中Table is read only的解决方法小结
- android的消息处理机制(图文+源码分析)―Looper/Handler/Message
- Android中的Looper对象详细介绍
- Android消息处理机制Looper和Handler详解
- AsyncTask陷阱之:Handler,Looper与MessageQueue的详解
- nginx: [warn] "log_format" directive used only on "http" level 解决方法
- ORA-01093: ALTER DATABASE CLOSE only permitted with no sessions connected
- Looper类浅析
- Android的线程使用来更新UI----Thread、Handler、Looper、Time...
- Handler Looper MessageQueue总结
- HTC One配件一览 MediaLink HD再次现身
- Android多线程Handler的使用,基于源代码理解。
- Android之Looper+Thread+handler
- on()、live()、bind()、one()的区别
- 单线程模型中Message、Handler、Message Queue、Looper之间的关系。
- one的配置文件说明
- Android的Looper和Handler消息处理机制详解
- 关于有些安卓手机安装应用的时候提示应用未安装 的解决办法之一