Android Compose ReComposition

Park Jae Hong·2023년 1월 27일
0

문제

: LazyColumn의 각 item들 에게 remember { mutableState(false) } 값을 통해서 색을 변경에 하고 있었다. 하지만 각 item 들을 외부에서 특정하게 초기화 하고 싶었지만 remember 값이 살아 있어 색이 초기화 되지 않는 오류가 발생헀다.

코드

StudyAllViewItem(studyInfo) { descIndex, description ->
            val selectedItem = StudyInfoItem(
                    studyInfo.id + descIndex,
                    studyInfo.detail,
                    studyInfo.king_name,
                    arrayListOf(description)
                )
            val selected by remember { mutableStateOf(false) }

            DescriptionTextView(
                studyState = studyState,
                selectedItem = selectedItem,
                backgroundColor = if (selected) Gray2 else Color.White,
                alphaText = if (selected || studyState != StudyType.ALL_BLANK_REVIEW.value) 1f else 0f,
                hintText = if (selected) allStudyData[index].description[descIndex] else description,
                changeSelectedItem = { item ->
                    if(selected) selectedItems.remove(item)
                    else selectedItems.add(item)
                    selected = selected.not()
                },
                changeButtonState = { studyPageViewModel.changeButtonState(selectedItems.size) },
                changeAllHintState = { studyPageViewModel.changeAllHintState() })
                }

실행 결과


해결방안 1

: remember를 할 때 selectedItems에 해당 item이 포함 되어있는지 여부를 저장한다.

StudyAllViewItem(studyInfo) { descIndex, description ->
            val selectedItem = StudyInfoItem(
                    studyInfo.id + descIndex,
                    studyInfo.detail,
                    studyInfo.king_name,
                    arrayListOf(description)
                )
                
            var selected = remember { selectedItems.contains(selectedItem) }

            DescriptionTextView(
                studyState = studyState,
                selectedItem = selectedItem,
                backgroundColor = if (selected) Gray2 else Color.White,
                alphaText = if (selected || studyState != StudyType.ALL_BLANK_REVIEW.value) 1f else 0f,
                hintText = if (selected) allStudyData[index].description[descIndex] else description,
                changeSelectedItem = { item ->
                    if(selected) selectedItems.remove(item)
                    else selectedItems.add(item)
                   
                },
                changeButtonState = { studyPageViewModel.changeButtonState(selectedItems.size) },
                changeAllHintState = { studyPageViewModel.changeAllHintState() })
        }

결과 : 이제 선택 조차 되지 않는다..

Try..

: selected 값을 따로 remember로 저장하고 배경색만 selectedItems.contains(selectedItem)으로 사용해 보았다.

StudyAllViewItem(studyInfo) { descIndex, description ->
            val selectedItem = StudyInfoItem(
                    studyInfo.id + descIndex,
                    studyInfo.detail,
                    studyInfo.king_name,
                    arrayListOf(description)
                )

            val selected by remember { mutableStateOf(false) }

            DescriptionTextView(
                studyState = studyState,
                selectedItem = selectedItem,
                backgroundColor = if (selectedItems.contains(selectedItem)) Gray2 else Color.White,
                alphaText = if (selected || studyState != StudyType.ALL_BLANK_REVIEW.value) 1f else 0f,
                hintText = if (selected) allStudyData[index].description[descIndex] else description,
                changeSelectedItem = { item ->
                    if(selected) selectedItems.remove(item)
                    else selectedItems.add(item)
                },
                changeButtonState = { studyPageViewModel.changeButtonState(selectedItems.size) },
                changeAllHintState = { studyPageViewModel.changeAllHintState() })
        }

결과

: 일단 기능적으로는 된다..! 하지만 계속 해서 remember의 값이 살아 있어, 선택되었는 item을 바로 선택했을 경우 한번 클릭이 안되는 것을 볼 수 있다.
그리고 이전에 selectedItems.contains(selectedItem)만 사용했을때는 선택 조차 되지 않았는데, 현재는 잘 선택되는 것으로 보아 기능적으로 선택은 잘 되지만 rememeber 값이 바뀌면서 recomposition에 대한 문제라고 판단 했다.

최종 해결방안

: 현재 selectedItems의 값을 viewModel에서 관리하고 있어서 selectedItems값이 변경 될 경우 자동적으로 recomposition이 일어난다고 생각했지만 그렇지 않았다. 그래서 selectedItem 값 자체를 remember { mutableStateListOf() } 값으로 관리 해야겠다고 판다.

 val selectedItems = remember { mutableStateListOf<StudyInfoItem>() }
 
 StudyAllViewItem(studyInfo) { descIndex, description ->
            val selectedItem = StudyInfoItem(
                    studyInfo.id + descIndex,
                    studyInfo.detail,
                    studyInfo.king_name,
                    arrayListOf(description)
                )

            val selected = selectedItems.contains(selectedItem)

            DescriptionTextView(
                studyState = studyState,
                selectedItem = selectedItem,
                backgroundColor = if (selectedItems.contains(selectedItem)) Gray2 else Color.White,
                alphaText = if (selected || studyState != StudyType.ALL_BLANK_REVIEW.value) 1f else 0f,
                hintText = if (selected) allStudyData[index].description[descIndex] else description,
                changeSelectedItem = { item ->
                    if(selected) selectedItems.remove(item)
                    else selectedItems.add(item)
                },
                changeButtonState = { studyPageViewModel.changeButtonState(selectedItems.size) },
                changeAllHintState = { studyPageViewModel.changeAllHintState() })
        }

결과

: 버그 없이 잘 실행되는 것을 볼 수 있다. remember를 사용할 때 recomposition 시점을 잘 생각해서 사용해 된다고 생각했다.

profile
The people who are crazy enough to think they can change the world are the ones who do. -Steve Jobs-

0개의 댓글