[안드로이드] 리사이클러뷰 데이터 필터링 구현하기

0
post-thumbnail

잡담

요즘은 학부생 때 막 제작했던 앱을 MVVM 구조로 리팩토링 하면서 시간을 보내고 있습니다.

기존에는 Firebase 데이터를 Sqlite DB로 불러와서 Sqlite 쿼리를 사용하여 데이터 필터링을 하였습니다.

그러나 이는 상당히 비효율적이었습니다. Firebase의 onDataChanged 콜백을 전혀 활용하지 않고, 앱 실행과 동시에 모든 Firebase데이터를 SQLite DB에 때려박고 앱을 시작했으니까요. 당시엔 MVVM에 대해 알지도 못했기 때문에 UI컨트롤러에 모든 로직을 때려박는 미친짓을 감행했었습니다. 이 때문에 초기 앱이 실행될때, 데이터를 받아와서 SQLite에 때려박는데 수초의 시간을 기다려야 했습니다. (지금도 이 앱을 갤럭시 스토어에 배포중인데 사용자분들께 너무 죄송스럽네요ㅠㅠ)

따라서 SQLite를 제거하고, Firebase의 onDataChanged를 이용하여 데이터가 갱신될 때 ViewModel의 LiveData를 갱신하는 로직으로 리팩토링 하였습니다. 그러나, SQLite의 편리했던 쿼리 기능이 없어지고 난 후에 어떻게 데이터를 날짜별로 필터링을 해야할까 대략 6시간 동안 고민하다가 로직을 겨우 짰네요.

데이터 필터링

이를 해결하기 위해 3개의 LiveData를 사용하였습니다.

var diaryData = MutableLiveData<MutableList<Diary>>()
var filteredList = MutableLiveData<MutableList<Diary>>()
var selectedDateTime = MutableLiveData<String>()

diaryData : Firebase에서 실시간으로 갱신되는 전체 데이터
filteredList : 날짜가 바뀜에 따라 새롭게 갱신되는 데이터
selectedDateTime : 날짜가 변경됨을 알리기 위한 데이터

로직은 selectedDateTime 이 갱신될때마다 (날짜가 바뀔 때마다) filteredList를 재 갱신 해주는 로직으로 작성하였습니다.
다음 코드는 filteredList를 갱신하는 코드입니다. 왜 substring을 썼냐면, date의 날짜 포맷이 yyyy-MM-dd(HH:mm:ss) 형태고, selectedDateTime의 날짜 포맷은 yyyy-MM-dd이기 때문에 filter 함수의 조건에 부합시키기 위해 가공했습니다.

fun setFilter() {
    filteredList.value = diaryData.value?.filter {
        it.date.isNotEmpty() && it.date.substring(0, 10) == selectedDateTime.value
    }?.toMutableList()

}

따라서 이제 해당 프래그먼트로 가서 라이브 데이터들을 관찰 후 데이터 갱신이 이루어질때 알맞은 로직을 넣어주면 됩니다.

날짜가 바뀌면, filteredList를 재갱신해주고, filteredList가 바뀌면 리사이클러뷰를 재 갱신 해주면 됩니다.

viewModel.selectedDateTime.observe(viewLifecycleOwner) {
    viewModel.setFilter()
}
viewModel.filteredList.observe(viewLifecycleOwner) {
    diaryAdapter.differ.submitList(it)
}

검색 필터링 구현방법?

만약 검색 필터링을 구현하고 싶다면 EditText의 addTextChangedListener 를 사용하여 edittext의 변경이 이루어질 때마다 setFilter()를 호출하면 되겠습니다. 다만 이는 데이터를 빠르게 입력할 수록 한꺼번에 많은 연산이 들어가기 때문에 코루틴을 사용하여 5초 정도의 딜레이를 주고 호출하는 것이 좋겠네요.

0개의 댓글