Looper.prepare()を呼び出していないスレッド内にハンドラーを作成できません


81

私にはアクティビティがあり、その中でクラスがあります。

text=new Dynamictext(...);
text.setText("txt");

私のDynamicTextJavaには、次のコードがあります。

public void setText(String text) {
    this.text=text;
    new asyncCreateText().execute();
    //this.createText(text);
}

//private Handler handler = new Handler();

private class asyncCreateText extends AsyncTask<Void, Void, Void> 
{
    @Override
    protected Void doInBackground(Void... unused) {
        return null;
    }

    @Override
    protected void onPostExecute(Void unused) {

    }
}

私は得る:

エラー/ AndroidRuntime(5176):原因:java.lang.RuntimeException:Looper.prepare()を呼び出していないスレッド内にハンドラーを作成できません

このエラーをどのように処理できますか?

ERROR/AndroidRuntime(5370): java.lang.ExceptionInInitializerError
ERROR/AndroidRuntime(5370):     at com.l.start.DynamicText.setText(DynamicText.java:125)
ERROR/AndroidRuntime(5370):     at com.l.start.OpenGLRenderer.initfonts(OpenGLRenderer.java:168)
ERROR/AndroidRuntime(5370):     at com.l.start.OpenGLRenderer.init(OpenGLRenderer.java:119)
ERROR/AndroidRuntime(5370):     at com.l.start.OpenGLRenderer.onSurfaceChanged(OpenGLRenderer.java:90)
ERROR/AndroidRuntime(5370):     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1120)
ERROR/AndroidRuntime(5370):     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:975)

ERROR/AndroidRuntime(5370): Caused by: java.lang.RuntimeException: 
    Can't create handler inside thread that has not called Looper.prepare()
ERROR/AndroidRuntime(5370):     at android.os.Handler.<init>(Handler.java:121)
ERROR/AndroidRuntime(5370):     at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
ERROR/AndroidRuntime(5370):     at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
ERROR/AndroidRuntime(5370):     at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
ERROR/AndroidRuntime(5370):     ... 6 more

フルスタックトレースを投稿できますか?バックグラウンドスレッドなどからUIメソッドを呼び出しているようです。
alexanderblom 2011

1
これにより、問題が詳細に説明されます。
mjosh 2013年

回答:


146

エラーは自明です...doInBackground()ループすることを意図していないため、に接続されていないバックグラウンドスレッドで実行されますLooper

ほとんどの場合、ハンドラーを直接インスタンス化することはまったく望ましくありません...doInBackground()実装が返すデータはすべてonPostExecute()、UIスレッドで実行されるデータに渡されます。

   mActivity = ThisActivity.this; 

    mActivity.runOnUiThread(new Runnable() {
     public void run() {
     new asyncCreateText().execute();
     }
   });

質問に表示されるスタックトレースに続いて追加:

AsyncTaskGLレンダリングスレッドから開始しようとしているようです...彼らもそうしないでくださいLooper.loop()。AsyncTasksは、実際にはUIスレッドからのみ実行されるように設計されています。

最も混乱の少ない修正は、おそらくあなたのActivity.runOnUiThread()を開始するRunnableで呼び出すことでしょうAsyncTask


1
答えは完全に正しいです。ただし、私の場合は、カスタムFtpUpload AsyncTaskクラスと出来上がりからいくつかのトースト(UIスレッドでの実行を試行)を削除する必要がありました。
ジョシュ

同じエラーが私に来ています私はそれを解決する方法を混乱させています私は説明を読みましたが、それを行う方法がわかりません誰もが私にコードを盗聴してください-Android
は私にとってすべて

32

上記の答えはすべて正しいですが、これが可能な最も簡単な例だと思います。

public class ExampleActivity extends Activity {
    private Handler handler;
    private ProgressBar progress;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        progress = (ProgressBar) findViewById(R.id.progressBar1);
        handler = new Handler();
    }

    public void clickAButton(View view) {
        // Do something that takes a while
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                handler.post(new Runnable() { // This thread runs in the UI
                    @Override
                    public void run() {
                        progress.setProgress("anything"); // Update the UI
                    }
                });
            }
        };
        new Thread(runnable).start();
    }
}

これは、アクティビティで宣言されたハンドラーのpost()メソッドを介して渡された完全に異なるスレッドからUIスレッドのプログレスバーを更新します。

それが役に立てば幸い!


22

この方法でバックグラウンドスレッドにハンドラーを作成します

private void createHandler() {
        Thread thread = new Thread() {
          public void run() {
               Looper.prepare();

               final Handler handler = new Handler();
               handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                       // Do Work
                        handler.removeCallbacks(this);
                        Looper.myLooper().quit();
                   }
                }, 2000);

                Looper.loop();
            }
        };
        thread.start();
    }

問題を解決するだけでなく、非常に説明的です。少し問題のある生地。どのようにそれをしたい場合は構造が変わるremoveCallbacksquitするときがWork行われますが、ない遅延に達しました。作業は事前定義された遅延より長く続く可能性があるためです。
Farid 2017年

12

Activity.runOnUiThread()私にはうまくいきません。この問題を回避するには、次のように通常のスレッドを作成しました。

public class PullTasksThread extends Thread {
   public void run () {
      Log.d(Prefs.TAG, "Thread run...");
   }
}

GL更新から次のように呼び出します。

new PullTasksThread().start();

このソリューションは、GLから呼び出すとうまくいきましたが、runメソッドでToastsを呼び出さないようにする必要があります。AsyncTaskは、GLからの呼び出しでは機能しませんでした。ありがとう!
アルベルトM.

AsyncTaskを置き換えるのに最適です。ありがとう!
IgorGanapolsky 2013年

5

UIスレッドからasyntaskを実行してみてください。私が同じことをしていなかったときに私はこの問題に直面しました!


3

これを試して

    Handler mHandler = new Handler(Looper.getMainLooper());
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
 //your code here that talks with the UI level widgets/ try to access the UI 
//elements from this block because this piece of snippet will run in the UI/MainThread.                                     
                            }
                        });

1
少し説明を追加してみてください。コードのみの回答は、SOではあまり評価されていません。
アレクセイ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.