
에러 상황

[ 안드로이드 ] RecylcerView + Filterable을 이용하여 실시간 검색 기능 구현하기
졸업 작품을 진행하면서 위와 같은 화면을 구현해야했다. 약품 리스트를 받아와서, 검색한 단어와 일치한 모든 약품들을 보여줘야했다. 추가로 일치하는 단어에는 하이라이팅까지 해줘야했다.
dongx2.tistory.com
이전에 위와 같은 화면을 구현하는 방법을 포스팅 했었는데, 위의 기능을 구현하면서 발생했던 에러에 대해서 적어보고자 한다.
에러 로그

검색을 하는 도중에 Incosistency detected. Invalid item postion ~~ 에러가 발생하면서 앱이 죽는 문제가 발생했다.
대충 어떤 부분에서 에러가 나는지 짐작은 되는데 정확히는 모르겠다. 이번 에러의 원인은 두 가지인 것으로 추측 된다.
추측 원인
기존 코드
- 아래 코드에서 위와 같은에러가 발생해서 두 번째 코드로 수정을 했었다.
filteredLIst =
if (userInput.isEmpty()) arrayListOf()
else {
val filteringList = ArrayList<Medicine>()
for (item in unFilteredList) {
if (item.itemName.contains(userInput)) filteringList.add(item)
}
filteringList
}
- 필터링된 리스트가 순간적으로 갱신 되면서 아이템을 참조하는 순간과 리스트가 비어있는 순간이 겹치면서 에러가 발생할 수도 있겠다라는 생각을 했기에 아래와 같이 코드를 수정했었다.
수정 코드
- 수정한 코드에서 어느정도 잘 동작하는 듯 싶었으나, 약품 검색에서는 잘 동작했지만, 병원 검색에서는 아래 코드로도 같은 오류가 발생했다.
- 처음엔 기존 코드에서 filteredList에 대입하는 과정이 문제라 생각했다.
- 대입하는 과정에서 기존 인스턴스가 일시적으로 사라지나 싶었지만, 아래 코드로도 오류가 나는 것을 보니 대입이랑은 상관 없는 것 같다.
val newFilteredList =
if (userInput.isEmpty()) arrayListOf()
else {
val filteringList = ArrayList<Medicine>()
for (item in unFilteredList) {
if (item.itemName.contains(userInput)) filteringList.add(item)
}
filteringList
}
filteredList.clear() // 문제의 부분
filteredList.addAll(newFilteredList)
- 대입이 문제가 아니라면 아마 filteredList.clear() 부분이 문제인 것으로 추측된다.
- 인스턴스가 사라지는게 아니라 리스트가 순간적으로 비는 것이 그나마 제일 가능성 높은 원인이었기에 이 부분을 고쳐보고자 했다.
해결 코드
override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(p0: CharSequence?): FilterResults {
// 필터링을 수행하는 부분에서는 기존 리스트를 건드리지 않는다.
userInput = "$p0"
val newFilteredList =
if (userInput.isEmpty()) arrayListOf()
else {
val filteringList = arrayListOf<Hospital>()
for (item in unFilteredList) {
if (item.dutyName.contains(userInput)) filteringList.add(item)
}
filteringList
}
// 필터링의 결과를 새 리스트에 담아서 리턴한다.
return FilterResults().apply { values = newFilteredList }
}
@SuppressLint("NotifyDataSetChanged")
override fun publishResults(p0: CharSequence?, p1: FilterResults?) {
// 결과를 발행할 때, 기존의 리스트에 필터링된 결과를 넣어준다.
filteredList = p1?.values as ArrayList<Hospital>
notifyDataSetChanged()
}
}
}
- 기존 코드는 필터링을 하는 동시에 filteredList의 값을 변경했었는데, 이 부분에서 문제가 발생한 것이 아닌가 싶다.
- 필터링을 할 땐 새로운 리스트를 만들어서 결과를 담고, 결과를 발행할 때 기존 리스트에 대입을한다.
- 위의 코드로는 일단 잘 동작하는데 좀 더 테스트해보면서 지켜봐야할 것 같다.
기타 에러
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
if(filteredList.size <= position) return
val hospital = filteredList[position] // -> 문제의 부분 IndexOutOfBoundsException 발생
holder.hospitalTitle.apply {
text = hospital.dutyName
val matchedIdx = text.indexOf(userInput, 0, true)
if(matchedIdx >= 0){
setForegroundColor(resources.getColor(R.color.primary_normal), matchedIdx, matchedIdx + userInput.length)
}
}
holder.address.text = "[${hospital.dutyAddress}] "
}
- 위의 에러와 직접적인 연관은 없는 것 같지만, try-catch 문으로 묶어서 테스트했을 때, filteredList에 접근하는 과정에서 IndexOutOfBoundsException이 발생했었다.
- 필터링된 리스트가 갱신 되면서 onBindViewHolder 메소드에서 참조하는 filteredList가 순간적으로 비게 되어 에러가 발생할 수 있을 것으로 예상이 된다.
'안드로이드 > 에러 해결' 카테고리의 다른 글

에러 상황

[ 안드로이드 ] RecylcerView + Filterable을 이용하여 실시간 검색 기능 구현하기
졸업 작품을 진행하면서 위와 같은 화면을 구현해야했다. 약품 리스트를 받아와서, 검색한 단어와 일치한 모든 약품들을 보여줘야했다. 추가로 일치하는 단어에는 하이라이팅까지 해줘야했다.
dongx2.tistory.com
이전에 위와 같은 화면을 구현하는 방법을 포스팅 했었는데, 위의 기능을 구현하면서 발생했던 에러에 대해서 적어보고자 한다.
에러 로그

검색을 하는 도중에 Incosistency detected. Invalid item postion ~~ 에러가 발생하면서 앱이 죽는 문제가 발생했다.
대충 어떤 부분에서 에러가 나는지 짐작은 되는데 정확히는 모르겠다. 이번 에러의 원인은 두 가지인 것으로 추측 된다.
추측 원인
기존 코드
- 아래 코드에서 위와 같은에러가 발생해서 두 번째 코드로 수정을 했었다.
filteredLIst =
if (userInput.isEmpty()) arrayListOf()
else {
val filteringList = ArrayList<Medicine>()
for (item in unFilteredList) {
if (item.itemName.contains(userInput)) filteringList.add(item)
}
filteringList
}
- 필터링된 리스트가 순간적으로 갱신 되면서 아이템을 참조하는 순간과 리스트가 비어있는 순간이 겹치면서 에러가 발생할 수도 있겠다라는 생각을 했기에 아래와 같이 코드를 수정했었다.
수정 코드
- 수정한 코드에서 어느정도 잘 동작하는 듯 싶었으나, 약품 검색에서는 잘 동작했지만, 병원 검색에서는 아래 코드로도 같은 오류가 발생했다.
- 처음엔 기존 코드에서 filteredList에 대입하는 과정이 문제라 생각했다.
- 대입하는 과정에서 기존 인스턴스가 일시적으로 사라지나 싶었지만, 아래 코드로도 오류가 나는 것을 보니 대입이랑은 상관 없는 것 같다.
val newFilteredList =
if (userInput.isEmpty()) arrayListOf()
else {
val filteringList = ArrayList<Medicine>()
for (item in unFilteredList) {
if (item.itemName.contains(userInput)) filteringList.add(item)
}
filteringList
}
filteredList.clear() // 문제의 부분
filteredList.addAll(newFilteredList)
- 대입이 문제가 아니라면 아마 filteredList.clear() 부분이 문제인 것으로 추측된다.
- 인스턴스가 사라지는게 아니라 리스트가 순간적으로 비는 것이 그나마 제일 가능성 높은 원인이었기에 이 부분을 고쳐보고자 했다.
해결 코드
override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(p0: CharSequence?): FilterResults {
// 필터링을 수행하는 부분에서는 기존 리스트를 건드리지 않는다.
userInput = "$p0"
val newFilteredList =
if (userInput.isEmpty()) arrayListOf()
else {
val filteringList = arrayListOf<Hospital>()
for (item in unFilteredList) {
if (item.dutyName.contains(userInput)) filteringList.add(item)
}
filteringList
}
// 필터링의 결과를 새 리스트에 담아서 리턴한다.
return FilterResults().apply { values = newFilteredList }
}
@SuppressLint("NotifyDataSetChanged")
override fun publishResults(p0: CharSequence?, p1: FilterResults?) {
// 결과를 발행할 때, 기존의 리스트에 필터링된 결과를 넣어준다.
filteredList = p1?.values as ArrayList<Hospital>
notifyDataSetChanged()
}
}
}
- 기존 코드는 필터링을 하는 동시에 filteredList의 값을 변경했었는데, 이 부분에서 문제가 발생한 것이 아닌가 싶다.
- 필터링을 할 땐 새로운 리스트를 만들어서 결과를 담고, 결과를 발행할 때 기존 리스트에 대입을한다.
- 위의 코드로는 일단 잘 동작하는데 좀 더 테스트해보면서 지켜봐야할 것 같다.
기타 에러
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
if(filteredList.size <= position) return
val hospital = filteredList[position] // -> 문제의 부분 IndexOutOfBoundsException 발생
holder.hospitalTitle.apply {
text = hospital.dutyName
val matchedIdx = text.indexOf(userInput, 0, true)
if(matchedIdx >= 0){
setForegroundColor(resources.getColor(R.color.primary_normal), matchedIdx, matchedIdx + userInput.length)
}
}
holder.address.text = "[${hospital.dutyAddress}] "
}
- 위의 에러와 직접적인 연관은 없는 것 같지만, try-catch 문으로 묶어서 테스트했을 때, filteredList에 접근하는 과정에서 IndexOutOfBoundsException이 발생했었다.
- 필터링된 리스트가 갱신 되면서 onBindViewHolder 메소드에서 참조하는 filteredList가 순간적으로 비게 되어 에러가 발생할 수 있을 것으로 예상이 된다.