๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๋นˆ ๊ตฌ๋ฉ ์ฑ„์šฐ๊ธฐ

[Android][Toast] Can't toast on a thread that has not called Looper.prepare()

Crashlytics์—์„œ ์ด์Šˆ ํ•ด๋‹น ๋ฐœ๊ฒฌ

 

๋ฌธ์ œ ๋ฐœ์ƒ

๋งˆ์ด๋„ˆ ์ด์Šˆ๋กœ ๋“ฑ์žฅํ•˜๊ณ  ์žˆ๋‹ค. (๊ณ  ํŒ๋‹จํ•˜๊ณ  ์žˆ๋‹ค. ์ œ๋ฐœ ๋งˆ์ด๋„ˆ ์ด์Šˆ์—ฌ๋ผ...)

 

์ด์Šˆ์— ๋Œ€ํ•œ ์„ค๋ช…๋“ค

https://stackoverflow.com/a/3875204

 

Can't create handler inside thread that has not called Looper.prepare()

What does the following exception mean; how can I fix it? This is the code: Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT); This is the exception: java.lang.RuntimeExce...

stackoverflow.com

https://gdlseed.tistory.com/70

 

์•ˆ๋“œ๋กœ์ด๋“œ ์ฝ”ํ‹€๋ฆฐ / can't toast on a thread that has not called looper.prepare()

Toast ๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค๊ฐ€ can't toast on a thread that has not called looper.prepare() ์—๋Ÿฌ๊ฐ€ ๋‚˜์˜ค๋ฉด์„œ App ๋น„์ •์ƒ ์ข…๋ฃŒ๋‹ค ๋˜์—ˆ๋‹ค. ๊ตฌ๊ธ€๋ง ํ–ˆ๋”๋‹ˆ UI ์Šค๋ ˆ๋“œ๊ฐ€ ์•„๋‹Œ ์Šค๋ ˆ๋“œ์—์„œ ํ† ์ŠคํŠธ ์ฐฝ์„ ๋„์šฐ๋ ค๊ณ  ํ•ด์„œ ๋ฐœ์ƒํ•œ ๋ฌธ

gdlseed.tistory.com

์ฆ‰, Toast ํ˜ธ์ถœ์€ UI ์ž‘์—…์ด๋ผ Main Thread์—์„œ ์ž‘์—…ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ์‹ค์ œ๋กœ Main Thread๊ฐ€ ์•„๋‹Œ ์“ฐ๋ ˆ๋“œ์—์„œ Toast ํ˜ธ์ถœ์ด ์ผ์–ด๋‚œ ๊ฒƒ.

 

๊ทธ๋Ÿผ ์ฝ”๋“œ์˜ ์–ด๋””์„œ, ์™œ ๋ฐœ์ƒํ–ˆ๋Š”๊ฐ€

RetrofitService.INSTANCE.getMyApi()
	.observeOn(Scheduler.io())
    .subscribeOn(Scheduler.io())
    .subscribe(data -> handleData(data),
    	error -> if (error != null) {
        	ExceptionExtensionsKt.handleErrorIfMyCustomException(error);
        }
    );

์ž๋ฐ”๋กœ ์ž‘์„ฑ๋œ ์ฝ”๋“œ์ด๋‹ค.

 

์—๋Ÿฌ ๊ณตํ†ต ์ฒ˜๋ฆฌ ๋ฉ”์†Œ๋“œ(์ € ๋ถ€๋ถ„์—์„œ ํ† ์Šคํ‹€ ํ˜ธ์ถœํ•œ๋‹ค.) ํ˜ธ์ถœ์ด Main Thread์—์„œ ์ด๋ค„์ง€๋Š” ๊ฒƒ์ด ์•„๋‹Œ ๊ฒƒ์„ ์ด์ œ ํ™•์ธํ–ˆ๋‹ค.

 

์ € ์—๋Ÿฌ ๊ณตํ†ต ์ฒ˜๋ฆฌ ๋ถ€๋ถ„์€ Main Thread์—์„œ ํ˜ธ์ถœ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋” ๋งŽ๊ธฐ๋Š” ํ•˜๋‹ค. 

 

์ด์Šˆ๋ฅผ ์–ด๋–ป๊ฒŒ ์ˆ˜์ •ํ•  ๊ฒƒ์ธ๊ฐ€

๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•๋“ค์ด ์žˆ๋‹ค.

 

1. ์ € ์—๋Ÿฌ ๊ณตํ†ต ์ฒ˜๋ฆฌ ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ชจ๋“  ๊ณณ์„ ๋’ค์ ธ์„œ Main Thread์—์„œ ์‹คํ–‰ํ•˜๋„๋ก ์ˆ˜์ •ํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ ์ง„ํ–‰ํ•  ๊ฒฝ์šฐ ์˜ˆ์ƒ๋˜๋Š” ๊ฒƒ๋“ค

  • ์ˆ˜๊ณ ๋กญ๋‹ค.
  • ์ˆ˜์ •ํ•ด์•ผํ•  ๋ถ€๋ถ„์„ ๋‚ด๊ฐ€ ๋†“์น  ์ˆ˜ ์žˆ๋‹ค. ๊ฒฐ๊ตญ์—” ๋˜ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒƒ์ด๋‹ค.
  • ์ € ์—๋Ÿฌ ๊ณตํ†ต ์ฒ˜๋ฆฌ ๋ฉ”์†Œ๋“œ์— ํ† ์ŠคํŠธ ํ˜ธ์ถœ์ด ์žˆ๋‹ค๋Š” ๊ฑธ ์ธ์‹ํ•˜์ง€ ๋ชปํ•œ (ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ์žŠ์–ด๋ฒ„๋ฆฐ ๋ฏธ๋ž˜์˜ ๋‚˜๋ฅผ ํฌํ•จํ•ด์„œ) ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ € ๋ฉ”์†Œ๋“œ๋ฅผ ์žฌ์‚ฌ์šฉ์‹œ Main Thread๊ฐ€ ์•„๋‹Œ ๊ณณ์—์„œ ํ˜ธ์ถœํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿผ ๋˜ ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

 

2. ์ € ์—๋Ÿฌ ๊ณตํ†ต ์ฒ˜๋ฆฌ ๋ฉ”์†Œ๋“œ ์•ˆ์—์„œ ํ† ์ŠคํŠธ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ถ€๋ถ„์„ Main Thread์—์„œ ์‹คํ–‰ํ•˜๋„๋ก ์ˆ˜์ •ํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ ์ง„ํ–‰ํ•  ๊ฒฝ์šฐ ์˜ˆ์ƒ๋˜๋Š” ๊ฒƒ๋“ค

  • 1๋ฒˆ๋ณด๋‹ค๋Š” ํ›จ์”ฌ ๋œ ์ˆ˜๊ณ ๋กญ๋‹ค.
  • ์ € ๋ฉ”์†Œ๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋Š” ์ž‘์—…ํ•˜๋Š” Thread์— ๋Œ€ํ•ด์„œ ์‹ ๊ฒฝ์“ธ ํ•„์š”๊ฐ€ ์—†๋‹ค.

2๋ฒˆ์œผ๋กœ ์„ ํƒํ•œ๋‹ค.

 

 

์ด์Šˆ ์ˆ˜์ •

์—๋Ÿฌ ๊ณตํ†ต ์ฒ˜๋ฆฌ ์ฝ”๋“œ ์•ˆ์„ ๊นŒ๋ณด๊ณ  ๋‚˜์„œ ๊ณผ๊ฑฐ์˜ ๋‚ด๊ฐ€ ๋†“์นœ ๋ถ€๋ถ„์„ ๋ฐœ๊ฒฌํ–ˆ๋‹ค.๐Ÿคฆ‍โ™€๏ธ 

์—๋Ÿฌ ๊ณตํ†ต ์ฒ˜๋ฆฌ ์ฝ”๋“œ ์•ˆ์˜ ์ž‘์—…๋“ค์ด Main Thread์—์„œ ์ž‘์—…ํ•ด์•ผํ•˜๋Š” ๊ฒƒ(ํ† ์ŠคํŠธ ํ˜ธ์ถœ ๋“ฑ)๊ณผ Thread์—์„œ ์ž‘์—…ํ•ด์•ผํ•˜๋Š” ๊ฒƒ(๋กœ์ปฌ ๋ฐ์ดํ„ฐ ์‚ญ์ œ ๋“ฑ)์œผ๋กœ ๋‚˜๋‰˜์–ด์ ธ ์žˆ๋Š”๋ฐ, ์ฝ”๋“œ ์ž‘์„ฑ ๋‹น์‹œ ์ด๊ฒƒ๋“ค์„ ๊ณ ๋ คํ•˜์ง€ ์•Š์•˜๋‹ค. ๐Ÿคฆ‍โ™€๏ธ 

์ด๋ฒˆ ์ด์Šˆ๋กœ ๋‚ด๊ฐ€ ๋†“์นœ ๋ถ€๋ถ„์„ ๋ฐœ๊ฒฌํ•ด์„œ ๋‹คํ–‰์ด๋‹ค.

 

์ฝ”๋“œ ์ˆ˜์ •์€ ๋Œ€๋žต ์ด๋Ÿฌํ•˜๋‹ค.

fun Throwable.handleErrorIfMyCustomException() {
	...
    
    Thread {
    	//UI
        Handler(Looper.getMainLooper()).post {
        	Timber.d("Toast Thread - ${Thread.currentThread().name}")
        	CustomToast.makeTest(context, R.string.msg, Toast.LENGTH_SHORT).show()
        }
        
        //Thread
        Timber.d("Logout Thread - ${Thread.currentThread().name}")
        LocalDataManager.deleteLocalData()
    }.start()
    ...
}

์ฝ”ํ‹€๋ฆฐ์œผ๋กœ ์ž‘์„ฑํ•œ ์ฝ”๋“œ์ด๋‹ค.

 

๋กœ๊ทธ๋กœ ๋™์ž‘ ํ™•์ธ ์™„๋ฃŒ.

 

๋กœ์ปฌ ๋ฐ์ดํ„ฐ ์‚ญ์ œ๋Š” ์›Œ์ปค ์“ฐ๋ ˆ๋“œ์—์„œ ๋™์ž‘๋จ์„ ํ™•์ธํ•จ
ํ† ์ŠคํŠธ ๋…ธ์ถœ์€ ๋ฉ”์ธ ์“ฐ๋ ˆ๋“œ์—์„œ ๋™์ž‘๋จ์€ ํ™•์ธํ•จ