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.