커뮤니티를 구현하다보면 반드시 만나는 기능이 있습니다.
게시글과 그 아래에 유저간의 소통을 할 수 있게끔 만들어주는 댓글이 필요합니다.
댓글의 경우는 대부분의 커뮤니티에서 채용하며 그만큼 여러 구현 예시들이 존재합니다.
그리고 그렇게 어려운 생각을 요구하지 않습니다.
단순히 리스트에 댓글 아이템을 보여주는 것으로 해결할 수 있습니다.
다만 댓글에서 신경써야 할 부분은 언제 댓글에 대한 API요청을 할 것이며 만약 댓글이 추가되거나 삭제, 혹은 다른 인터랙션이 필요한 경우에는 리스트업을 어떻게 시킬것인가에 대한 고민만 하면 됩니다.
댓글에 대한 구현을 할때에는 댓글이 많을 경우를 생각하여 구현했다면 보통 PagingDataAdapter를 이용하여 구현했을 것입니다.
따라서 어댑터에 직접적인 데이터를 넣어주는 방식이 아닌 Flow를 열고 수집을 하면서 수집한 데이터들이 변경될때마다 어댑터에서 인지한 후 리스트를 refresh해줄 것입니다.
이를 이용한다면 댓글 리스트업에 대한 방식으로는
이라는 기본적인 방법이 있을 것입니다.
하지만 이 방식의 단점은 댓글을 한개만 작성, 수정, 삭제하더라도 어댑터의 모든 데이터들이 리프레시 될것이라는 점입니다.
그렇다면 사용자로 하여금 모든 댓글에 대한 움직임이 보일 수 있습니다.
따라서 이 방식에서 조금 더 생각을 해보면 다른 방식을 찾을 수 있을 것입니다.
그 방식은 어댑터에 변경된 데이터 값에 대한 정보를 입력해주는 것입니다.
어댑터 내부에 먼저 함수를 작성합니다.
다음 예시는 한 아이템의 내용을 수정하였을때를 구현한 부분입니다.
기본적으로 아이템에 대한 정보가 필요합니다.
아이템에 대한 정보를 확인 후 어댑터 내부에서 해당 아이템을 찾습니다.
변경하려는 아이템의 정보를 아는 방법에 대해서는 상황마다 다르지만 보통은 유니크한 값인id를 이용합니다. snapshot을 이용하면 페이징의 현재 컨테이너에 있는 모든 데이터들에 대하여 접근이 가능합니다.
private fun findIndexed(predicate: (Long) -> Boolean): Pair<Int, ListData>? {
for ((i, item) in snapshot().withIndex()) {
item?.post?.let {
if (predicate(it.id)) {
return Pair(i, it)
}
}
}
return null
}
위의 코드를 이용하여 업데이트 할 아이템에 접근합니다.
업데이트 할 아이템에 접근했다면 해당 아이템을 업데이트 후 notifyItemChanged를 통하여 해당 아이템을 업데이트 시켜줍니다.
fun updateItem(item: ItemComment) {
findIndexed {
item.id == it
}?.let {
it.second.apply {
contents = item.contents
description = item.description
}
this.notifyItemChanged(it.first)
}
}
위의 방법을 사용하게 된다면 전체 리스트를 리프레시 하지 않고도 업데이트가 가능해집니다.
업데이트를 하는 시기에 대한 생각을 해볼 수 있습니다.
기본적으로는 Request에 대한 Response가 오게 된다면 받은 Response를 가지고 데이터를 업데이트 할 수 있겠습니다.
하지만, 만약 좀 더 부드럽고 빠른 처리를 원한다면 Mock을 이용하는 방법이 있습니다.
Request를 보내고 Response가 오기 전 먼저 업데이트를 해버리는 것입니다.
업데이트를 할 떄 우리는 보통 해당 업데이트에 필요한 데이터들을 Request에 담아서 보냅니다.
그렇다는것은 사실 업데이트에 필요한 정보를 이미 알고있다는 점이고 그걸 이용해서 미리 업데이트가 가능합니다.
위의 방식대로 해당 아이템을 찾고 리사이클러뷰에 필요한 데이터들을 이용하여 업데이트를 해주면됩니다.
만약 Request의 결과로 Error가 발생하게 된다면 아이템의 처리는 Response를 받는 곳에서 catch를 이용하여 에러에 대한 정보를 받고 그것에 따라서 적절한 처리를 진행하면 됩니다.