无法在主线程中创建处理程序?

时间:2012-06-14 20:09:42

标签: android handler

执行下面的代码时,用户在手机上收到错误,我在运行AsyncTask进行Web服务调用之前,正在检查用户当前是否正在通话。我这样做的原因是因为有些人在通话时丢失了互联网连接,所以我每5秒检查一次是否正在通话。如果不是,则调用AsyncTask

do{
        Handler handler = new Handler();
        handler.postDelayed(new Runnable(){

            @Override
            public void run() {

                 onCall = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE))
                        .getCallState() != TelephonyManager.CALL_STATE_IDLE;
                 if(!onCall){
                     new CallRegWS().execute();
                 }  
            }
        },5000);
    }while(onCall);

我没有完整的堆栈跟踪只显示错误

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

显然不太有用,但这就是我必须继续下去。他们不断得到这个错误,所以当我创建处理程序时它必须发生。

这一切都是在main thread完成的,所以我不知道问题是什么,对如何解决这个问题的任何见解?

更新 这是从服务调用的,方法是在一个单独的类

3 个答案:

答案 0 :(得分:7)

尝试Handler handler = new Handler(Looper.getMainLooper());

此外,请参阅有关此错误的帖子:http://levinotik.com/loopers-handlers-runtimeexceptions-explained/

答案 1 :(得分:2)

首先,您必须知道,处理程序会自动附加到文档中指定的创建的线程:

处理程序类概述

  

Handler允许您发送和处理与线程的MessageQueue关联的Message和Runnable对象。每个Handler实例都与一个线程和该线程的消息队列相关联。当您创建一个新的Handler时,它被绑定到正在创建它的线程的线程/消息队列 - 从那时起,它将消息和runnables传递给该消息队列并在消息出来时执行它们队列。 Handler | Android Developers

现在,在计算时,由于当前线程没有消息队列,为了正常工作,线程需要一个实际的" Queue",而这正是系统告诉你做什么,通过调用Looper.prepare()你在你创建的线程中创建一个Message Looper,因为默认情况下Threads没有文档中提到的Message looper:

Looper课程概述

  

用于为线程运行消息循环的类。默认情况下,线程没有与之关联的消息循环;创建一个,在运行循环的线程中调用prepare(),然后循环()让它处理消息,直到循环停止。 Looper | Android Developers

换句话说,以简单的方式,主UI已经准备好了一个消息队列,这就是为什么你在"中调用新的Handler()时没有看到错误的原因。 onCreate,onStart,onResume等...",但对于创建的任何工作线程,系统需要一个队列来在使用处理程序时发送消息,虽然代码没有显示它,我打赌代码是在工作线程中执行AsyncTask的普通Thread或doInBackground方法以及导致错误的原因,以避免在从工作线程创建处理程序之前始终调用Looper.prepare。

希望这有助于。

问候!

答案 2 :(得分:1)

你怎么知道它在主线程上运行?什么时候和哪里被召唤?而不是在使用它之前创建处理程序,而是在Activity或服务的onCreate方法中创建它(取决于它是什么)。然后在onDestroy中将值清空。