일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- java
- 게임개발
- 2d게임
- submodule sourcetree
- 쿼터뷰
- Android Studio
- 안드로이드
- Unity
- 앱개발
- gitlab submodule
- github
- 안드로이드개발
- 코틀린
- 개발
- 카페오냥
- 목서버
- Android
- 서브모듈 sourcetree
- 유니티
- 내 맘대로 정리한 안드로이드
- Kotlin
- DataBinding
- 서브모듈 pull
- 티스토리
- github submodule
- GIT
- firebase
- 앱
- 안드로이이드 submodule
- 타이쿤
- Today
- Total
Uing? Uing!!
[안드로이드 삽질기록] java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling androidx.recyclerview.widget.RecyclerView 본문
[안드로이드 삽질기록] java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling androidx.recyclerview.widget.RecyclerView
Uing!! 2021. 7. 16. 01:52발단
액티비티 내에 RecyclerView가 있었고, 스크롤 관련된 로직이 많았다.
그런데 특정 상황에서 이 글의 제목과 같이,
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling androidx.recyclerview.widget.RecyclerView
라는 크래시로그가 나는 것을 발견했다. OMG.
해당 크래시가 발생하는 위치는 notifyItemInserted였다.
삽질
스택트레이스 메시지를 보고 당연히 스크롤과 관련된 문제일거라고 생각했다.
구글링을 해 보아도 stackOverflow에서는 notifyItem~ 메소드가 스크롤 이후에 실행될 수 있도록 post{}하라는 의견이 많았다.
하지만 notify 메소드를 쓰는 위치가 한두 군데가 아니어서 일일이 처리하기가 난감하기도 했고, post를 통해 임시방편으로 문제가 발생하지 않도록 막는 것이 찝찝하기도 했다.
그래서 근본적인 문제가 무엇일지에 대해 조금 더 생각했다.
결국 알아낸 사실은, 에러 메시지의 '... computing a layout or scrolling ...' 중에서 문제가 되는 부분은 'scrolling'이 아닌 'computing layout'이라는 것이었다.
(에러 문구를 다시금 읽어 보아도, 이 stackTrace 메시지를 가지고 해법을 바로 찾기가 용이하지는 않은 것 같다. 이렇게 적어 놓으면 대부분 스크롤 문제라고 생각하게 되지 않나...?)
이 문제가 발생한 원인은 리사이클러뷰 어댑터에 있었다.
onBind는 최소한의 역할만 하는 것이 좋은데, 기능 상 onBind가 너무 비대해져서 놓친 코드가 있었던 것이다.
이 어댑터는 onCreate에서 textChangedListener를 추가하는데, 특정 상황에서 notifyItemInserted를 호출하게 되어 있었다.
그런데 onBind에서 setText로 아이템뷰에 텍스트가 설정되면, onCreate에서 연결해 둔 onTextChanged가 호출되었고, 위의 '특정 상황'이 발동해서 notifyItemInserted가 호출된 것이다.
즉, 결과적으로 onBindViewHolder 내부에서 notify~가 호출되고 있어 생기는 에러였다.
결론
notifyItemInserted가 onBindViewHolder내부에서 호출되는 일이 없도록 코드를 수정하니 같은 상황에서도 더이상 크래시가 발생하지 않았다.
이후에도 onBind에서 notify가 불리지 않도록 주의하고,
또 놓치는 코드가 생길 수 있으므로 onCreate, onBind가 너무 비대해지는 것은 유의해야 할 듯하다.
'Android' 카테고리의 다른 글
[안드로이드 팁] Chrome DevTools: 웹뷰를 디버깅해 보자! (0) | 2021.07.30 |
---|---|
[내 맘대로 정리한 안드로이드] findViewById의 사용을 최소화해야 하는 이유와 대체 방법(ViewBinding) (1) | 2021.07.16 |
[내 맘대로 정리한 안드로이드] LiveData의 데이터 누락: Observer는 '모든' 이벤트를 100% 받아올 수 있을까? (0) | 2021.07.16 |
[안드로이드 팁] Inspect Code: 프로젝트 내의 모든 Lint 확인하기 (0) | 2021.03.31 |
[내 맘대로 정리한 안드로이드] dp와 sp: 폰트 크기로 무엇을 써야 하는가? (0) | 2021.03.30 |