본문 바로가기
앱 제작/키워드 알림 앱

Inconsistency detected. Invalid view holder adapter positionMyNoticeViewHolder (부제: 스크롤을 너무 빠르게 내렸을 때 생기는 문제)

by Kim Juhwan 2021. 1. 27.

1. 나의 해결법

 

스크롤을 빠르게 내리니까 앱이 종료되어 버린다.

 

refreshRecyclerView (새로고침 기능)

endlessRecyclerView (목록의 끝에 도달하면 다음 항목 불러오는 기능)

이 두 개를 같이 사용하다가 문제가 생겼다.

새로고침을 한 다음에 스크롤을 빠르게 내리면 앱이 강제 종료가 되어버린다.

 

 

이러한 에러 메시지가 떴다.

[Inconsistency detected. Invalid view holder adapter positionMyNoticeViewHolder{38334d0 position=8 id=-1, oldPos=-1, pLpos:-1 no parent]

 

IndexOutOfBoundsException이 떴고 position에 대해 이야기하는 걸 보니

새로고침을 하고 리스트를 로드하는 과정에서 문제가 있는 것 같았다.

실제로도 새로고침을 하지 않고 빠르게 스크롤을 해도 에러가 안뜨는데 꼭 새로고침 이후에만 문제가 생겼다.

 

아무튼 그래서 찾아낸 원인

새로고침이 다 되기도 전에 스크롤을 내려서(아이템 항목을 불러와서)이다.

화면에는 이전 아이템 목록이 그대로 보이기 때문에 벌써 새로고침이 다 된 것처럼 보여서 인지하지 못했다.

 

 

refresh_layout.setOnRefreshListener(PullRefreshLayout.OnRefreshListener {
    activity!!.window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) // 화면 터치 못하게 하기
    notices.clear() // 항목 리셋
    crawler.activateBot(page) // 새로운 항목 불러오기 (내가 만든 메서드)
            
    val handler = android.os.Handler()
    handler.postDelayed({
        keywordAdapter!!.notifyDataSetChanged() // 새로고침
        refresh_layout.setRefreshing(false) // 새로고침 아이콘 없애기
        activity!!.window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) // 이제 터치가능
    }, 1000) // 1초 딜레이
})

이 어이없는 에러가 발생한 이유는

내가 콜백메서드와 비동기 실행에 대한 이해가 부족해서 발생했다.

(어휴 그러니까 공부 좀 하지 ㅡㅡ)

우선 임시방편으로 새로고침할때 무조건 1초의 딜레이를 가지게 하고 사용자가 화면을 터치하지 못하도록 막았다.

실제로 걸리는 시간이 1초보다 짧으면 손해고 1초보다 길면 또 에러를 뱉어낼 것이므로.. 꼭 고쳐야 한다.

 

(2021.02.14 추가)

 

[kotlin] 코루틴 공부하기 (비동기 처리, 서버 딜레이 처리)

빌어먹을 코루틴... 저번에 공부하다가 도저히 못해먹겠어서 포기했다가 오늘 다시 도전했다. 항상 느끼는 거지만 아무것도 모를 땐 그렇게 어렵게 느껴지다가 또 막상 성공하면 아 이걸 왜 이

todaycode.tistory.com

코루틴을 이용해서 문제를 해결하였다. 위 글 참고!

 

2. 다른 해결법(1)

 override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        var safePosition = holder.adapterPosition
        title.text = notices[safePosition].title
 }

나한테는 통하지 않은 방법이지만

저 에러가 뜨는 이유는 여러 가지일 테니 기록을 해두려고 한다.

방법은 간단하다. onBindViewHolder에서 매개변수로 넘어오는 position대신

holder.adapterPosition을 사용하는 것이다.

 

 

[Android] java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionMyViewHolder{152d0dc

오늘도 안드로이드 개발을 하다가 java.lang.IndexOutOfBoundsException:Inconsistency detected. Invalid view holder adapter positionMyViewHolder{152d0dc position=5 id=-1, oldPos=-1, androidx...

breakcoding.tistory.com

이 블로거분의 글을 참고했다. 이분은 이 방법으로 해결하셨다고 한다.

 

 

 

3. 다른 해결법(2)

class LinearLayoutManagerWrapper: LinearLayoutManager {
    constructor(context: Context) : super(context) {}
    constructor(context: Context, orientation: Int, reverseLayout: Boolean) : super(context, orientation, reverseLayout) {}
    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {}
    override fun supportsPredictiveItemAnimations(): Boolean { return false }
}

이런 클래스를 생성하고

 

mRecyclerView.layoutManager = LinearLayoutManager(context) // 이거 대신

val linearLayoutManagerWrapepr = LinearLayoutManagerWrapper(context!!, LinearLayoutManager.VERTICAL, false) // 이걸 만들어서
mRecyclerView.layoutManager = linearLayoutManagerWrapper // 이걸 넣는다.

LinearLayoutManager 대신에 넣는 방법이다.

나는 이 방법을 쓰고 해결된 듯 보였으나(?)

다른 에러가 대신 떠서 포기했다.

 

 

 

[안드로이드] Inconsistency detected. Invalid view holder adapter positionViewHolder

최근 크래시 리포트에서 RecyclerView와 관련된 오류가 하나 집계되었다. Inconsistency detected. Invalid view holder adapter positionViewHolder 찾아보니 삼성 디바이스에서 발생하는 이슈로 올라와있..

mparchive.tistory.com

이 블로거 분의 글을 참고했다.

 

 

 

4. 다른 해결법(3)

 

[코틀린] infinite/endless scroll(무한 스크롤)과 recyclerView

1. infinite/endless scroll  1-1. 개념  1-2. Progress Bar  1-3. 아이템 뷰(ItemView)  1-4. 홀더(Holder)  1-5. 스크롤 리스너(Scroll Listener)  1-6. 다른 최하단 도달 감지 방법 2. Adapter  1-1...

todaycode.tistory.com

스크롤을 빠르게 내렸을 때

리스트의 최하단에 도달했는지 감지가 제대로 안되는 경우도 있는 것 같다.

위 게시글의 1-5, 1-6 부분을 참고해서 보완을 해보는 것도 좋을 것 같다.

반응형

댓글