본문 바로가기

만났던 에러들

Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

안드로이드에서 roomDB를 쓰는데 아래 에러를 만났다. Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

 

우선 위의 에러를 해결한 방법을 설명하기 앞서서 하나 알아둬야 할게있다.

안드로이드에선 외부통신(핸드폰 내부에 저장한 데이터 RoomDB나 SQLlite, Retrofit을 통해서 외부 api 통신에서도)을 메인 스레드에서 동작시키면 안된다.

자 그렇다고 치더라도...

뭔가 이상하다. 코루틴을 사용해서 veiwModelScope 에서 메소드를 실행하면 자동적으로 메인스레드가 아니라 워커 스레드에서 동작하는 것으로 알고 있는데 메인스레드에서 코드가 동작하고 있다는 말일까?

 

아래는 에러가 발생한 부분을 로그로 찍었을때 코드다.

 

LoginActivityViewModel.kt

    // 이메일로 로그인한 사용자의 정보를 불러오는 메소드
    private fun getSavedUserLoginInfo(context : Context) = viewModelScope.launch {
        signInUsecase.getSavedUserLoginInfo(context).collect{
            Logger.v(it.toString())
        }
    }

 

로그로 확인을 해보니 메인스레드위에서 동작하는게 아닌건 맞았다.

 

본문과는 무관한 내용이지만 Logger라이브러리를 사용하면 현재 코드가 어떤 스레드에서 동작하는지까지 볼 수 있어서 매우 좋다. 다들 잘 활용해보자.

아래 블로그를 활용하면 Logger를 사용하는 방법이 나와있다.

https://github.com/orhanobut/logger

 

GitHub - orhanobut/logger: ✔️ Simple, pretty and powerful logger for android

✔️ Simple, pretty and powerful logger for android. Contribute to orhanobut/logger development by creating an account on GitHub.

github.com

 

어쨌든, 검색해서 찾아보니까 따로 정의를 해주는게 아니면 main스레드에서 코드가 동작한다고 하니까 조치를 취해줘야 할 필요가 있었다.

 

https://stackoverflow.com/questions/63166046/why-do-i-get-cannot-access-database-on-the-main-thread-since-it-may-potentially

 

Why do I get 'Cannot access database on the main thread since it may potentially lock the UI for a long period of time.' error i

I get the error "java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time." when I run Code A, why? The Co...

stackoverflow.com

 

" Option B uses viewModelScope.launch(Dispatchers.IO) which means the code runs on the IO dispatcher. As this isn't the main thread, it succeeds."

 

아래와 같이 코드를 수정해서 코드가 코루틴에게 main스레드가 아니라 서브스레드에서 동작시켜줘야 한다고 알려주자. 

// 이메일로 로그인한 사용자의 정보를 불러오는 메소드
    private fun getSavedUserLoginInfo(context : Context) = viewModelScope.launch(Dispatchers.IO) {
        signInUsecase.getSavedUserLoginInfo(context).collect{
            Logger.v(it.toString())
        }
    }