본문 바로가기
Android/Exceptions

java.lang.RuntimeException: Can't toast on a thread that has not called Looper.prepare()

by featherwing 2020. 6. 5.
반응형

 

1. Log로 실행 유무를 확인하다가 Toast로 바로 확인해야 할 부분이 생겨서 Log를 Toast로 변경하였다가 발생하였습니다. 아무생각 없이 넣다보면 가끔 생기게됩니다.  JobIntentService를 처음 다루다가 발생하게 되었습니다. Service니까 당연히 Background로 돌아가게 되는부분인데 생각없이 하다보니 오랜만에 해당 Exception을 확인하게 되었습니다.

 


2. 원인은 명확합니다.

해당 Exception의 세부적인 부분을 보면 아래와 같습니다.

 java.lang.RuntimeException: An error occurred while executing doInBackground()
        at android.os.AsyncTask$4.done(AsyncTask.java:399)
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
        at java.util.concurrent.FutureTask.run(FutureTask.java:271)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
     Caused by: java.lang.RuntimeException: Can't toast on a thread that has not called Looper.prepare()
        at android.widget.Toast$TN.<init>(Toast.java:898)
        at android.widget.Toast.<init>(Toast.java:204)
        at android.widget.Toast.makeText(Toast.java:599)
        at android.widget.Toast.makeText(Toast.java:568)
        at co.yggdrasil.todayon.noti.RebootJobIntentService.j(RebootJobIntentService.java:68)
        at co.yggdrasil.todayon.noti.RebootJobIntentService.g(RebootJobIntentService.java:51)
        at androidx.core.app.f$a.a(JobIntentService.java:392)

 

백그라운드에서 돌아가는 부분에서 메인 쓰레드에서 관리해야 하는 Ui인 Toast를 띄워주었으니 발생하게 되었습니다.

 

해당 Exception과 반대 상황은 메인쓰레드에서 백그라운드에서 관리해야 하는 작업을 시도하는 경우인데 네트워크 동기화 등의 작업을 Ui에서 할때가 가장 흔한 예가 됩니다. 백그라운드에서 수행하는 작업은 AsyncTask나 Corutine, RxJava등을 이용해서 비동기 작업을 구현 해 주면 되는데, 반대로 UI 쓰레드에 대한 변경을 background에서 하려면 어떻게 해야 할까요.

 

 


 

3.아래와 같이 handler를 이용하면 됩니다.

간단하게 Toast를 띄워주는 작업이라 아래의 코드를 만들어놓고 사용했습니다.

 

   final Handler mHandler = new Handler();
    void showToast(final CharSequence text) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
            }
        });
    }

handler에 대한 자세한 내용은 안드로이드 개발자 문서의 Communicate with the UI thread를 참고 해 주세요.

반응형

댓글