Only one Looper may be created per thread

来源:互联网 发布:达内 java培训机构 编辑:程序博客网 时间:2024/05/09 00:20
在开发一套智能家居的APP时,因为要让APP自动根据用户操作过的数据来更新自己的状态。

出现大致一个这样的代码结构(该结构不是原项目中的,这是随便写了一个与项目代码结构一致):

class LoopThread extends Thread {@Overridepublic void run() {// TODO Auto-generated method stubsuper.run();Looper.prepare();postt(100);Log.e("sos", "Looper 【外面的】  Log");Looper.loop()}}public void postt(int tmp) {while (true) {new Handler().postDelayed(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubLog.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);
是因为线程下又开有线程。


0 0