이전에 LiveData를 갱신해서 가져오지 않아서, UI에서 사용하는 list를 따로 생성하여, UI의 Lifecycle을 고려하고 mutableState를 사용하여 Lifecycle에서 1번만 가져오도록 하는 등 복잡한 방식으로 해결했었습니다.
최근 포트폴리오를 작성하면서 이 에러에 대해 다시 분석하였고 제대로 고칠 수 있었습니다.
viewModel.stockNameList.observe(LocalLifecycleOwner.current){
companyList.clear()
companyList.addAll(it)
}
이 방식에서 문제가 되었던 부분은 LocalLifecycleOwner.current 부분입니다.
이러한 방식은 주로 xml로 코드를 작성할 때 사용됩니다. 저는 이 방식이 익숙하기에 원래 하던 방식을 따랐습니다.
- 반응형 패러다임과 충돌:
- Compose는 선언적이고 반응형 패러다임에 따라 작동합니다. 즉, 데이터가 변경되면 UI가 자동으로 업데이트됩니다.
- LifecycleOwner를 사용하는 방식은 보통 기존의 관찰자 패턴을 따르며, 이는 명령형 패러다임에 가깝습니다. 두 가지 패러다임이 서로 충돌할 수 있습니다.
- 수명 주기 관리의 어려움:
- Compose에서는 수명 주기를 자동으로 관리하는 반면, LifecycleOwner를 직접 사용하는 경우에는 수동으로 관리해야 합니다.
- Composable은 화면 구성 시점에 따라 생명 주기가 변할 수 있어 LifecycleOwner와 수명 주기를 맞추는 것이 어렵습니다.
따라서 compose 환경에서 LiveData를 관찰할 때는 observeAsState 함수의 사용이 권장됩니다.
이 함수는 LiveData를 직접 State로 바꾸는 함수입니다. 이를 통해 compose의 수명 주기와 자동적으로 연결됩니다.
수명 주기 관리를 compose에게 맡김으로서 우리는 수명 주기 관리에 신경쓰지 않아도 됩니다.
아래는 수정한 코드입니다.
/************주식 이름 목록 가져오기*************/
val stockNameList by viewModel.stockNameList.observeAsState(initial = emptyList())
LazyColumn() {
items(stockNameList) {
CompanyListCard(it, stockNameList.toMutableStateList())
}
}
viewModel에서 가져온 값을 바로 LazyColumn에 넣어줌으로써 UI에 반영시킵니다.
그러면 데이터의 값이 변경될 때 이를 인식하여 가져옵니다.