Looper.prepare ()를 호출하지 않은 스레드 내부에 핸들러를 만들 수 없습니다.


81

나는 활동이 있고 거기에 수업이 있습니다.

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

내 DynamicText Java에는 다음 코드가 있습니다.

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) {

    }
}

나는 얻다:

ERROR / 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

1
이것은 문제를 자세히 설명합니다.
— mjosh

답변:


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 클래스와 짜잔에서 일부 Toasts (UI 스레드에서 실행 시도)를 제거해야했습니다.
— Josh

같은 오류가 나에게오고 있습니다. 어떻게 해결해야하는지 혼란 스럽습니다. 설명을 읽었지만 어떻게해야하는지 모르겠습니다. 누구든지 나에게 코드 snippest를 줄 수 있습니다
— 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();
    }

문제를 해결할뿐만 아니라 매우 설명 적입니다. 약간의 문제 반죽. 원하는 경우 구조가 어떻게 변경 removeCallbacks되고 quit언제 Work완료되지만 지연되지는 않습니다. 작업이 미리 정의 된 지연보다 오래 지속될 수 있기 때문입니다.
— Farid

12

Activity.runOnUiThread()나를 위해 작동하지 않습니다. 이 방법으로 일반 스레드를 만들어이 문제를 해결했습니다.

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

다음과 같이 GL 업데이트에서 호출합니다.

new PullTasksThread().start();

이 솔루션은 GL에서 호출했지만 실행 메서드에서 Toasts를 호출하지 않는지 확인해야합니다 !! AsyncTask는 GL에서 호출하지 않았습니다. 감사!
— Alberto M.

AsyncTask를 대체 할 때 잘 작동합니다. 감사!
— IgorGanapolsky

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
약간의 설명을 추가하십시오. 코드 전용 답변은 그렇게 평가되지 않습니다.
— Alexei
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.