1

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ため、何が問題なのかわかりません。これを修正する方法についての洞察はありますか?

更新 これはサービスから呼び出され、メソッドは別のクラスにあります

4

3 に答える 3

7

試すHandler handler = new Handler(Looper.getMainLooper());

また、このエラーに関するこの投稿を参照してください: http://levinotik.com/loopers-handlers-runtimeexceptions-explained/

于 2012-06-14T20:29:01.300 に答える
2

まず最初に、ハンドラーはドキュメントで指定されているように作成されたスレッドに自動的にアタッチすることを知っておく必要があります。

ハンドラークラスの概要

ハンドラーを使用すると、スレッドのMessageQueueに関連付けられたMessageオブジェクトとRunnableオブジェクトを送信および処理できます。各Handlerインスタンスは、単一のスレッドとそのスレッドのメッセージキューに関連付けられています。新しいハンドラーを作成すると、それを作成しているスレッドのスレッド/メッセージキューにバインドされます。その時点から、メッセージとランナブルがそのメッセージキューに配信され、メッセージから出てきたときに実行されます。列。ハンドラー| Android開発者

さて、それを考慮に入れて、現在のスレッドにはメッセージキューがないので、スレッドが正しく機能するためには、実際の「キュー」が必要です。これは、Looper.prepareを呼び出すことによってシステムが指示していることです。 ()ドキュメントに記載されているように、デフォルトではスレッドにメッセージルーパーがないため、作成したスレッド内にメッセージルーパーを作成しています。

ルーパークラスの概要

スレッドのメッセージループを実行するために使用されるクラス。デフォルトでは、スレッドにはメッセージループが関連付けられていません。作成するには、ループを実行するスレッドでprepare()を呼び出してから、loop()を呼び出して、ループが停止するまでメッセージを処理します。ルーパー| Android開発者

言い換えると、簡単な方法で、メインUIにはメッセージキューがすでに用意されているため、「onCreate、onStart、onResumeなど」内で新しいHandler()を呼び出しても、そのエラーは表示されませんが、作成されたワーカースレッドの場合、ハンドラーを使用するときにシステムにメッセージを送信するためのキューが必要ですが、コードには表示されていませんが、コードはAsyncTaskの通常のThreadまたはdoInBackgroundメソッドのいずれかのワーカースレッドで実行されていると思います。エラーの原因は、ワーカースレッドからハンドラーを作成する前に、常にLooper.prepareを呼び出すことを忘れないようにするためです。

お役に立てれば。

よろしく!

于 2013-03-18T23:11:17.650 に答える
1

これがメインスレッドで実行されていることをどのように知っていますか? そして、これはいつ、どこから呼び出されますか? ハンドラーを使用する直前に作成する代わりに、Activity または Service の onCreate メソッドで作成します (これが何であるかによって異なります)。次に、onDestroy で値を null にします。

于 2012-06-14T20:17:47.513 に答える