최근에 StaggeredGridLayoutManager를 사용한 즐겨찾기 화면에서 다음과 같은 문제가 발생했습니다:
- 즐겨찾기 화면에서 첫 번째 사진을 클릭하여 상세 보기로 이동
- 사진 상세 화면에서 즐겨찾기를 해제
- 뒤로 가기를 눌러 다시 즐겨찾기 화면으로 돌아오면 빈 화면이 보여짐
이 문제는 StaggeredGridLayoutManager에서 아이템을 재배치하는 과정에서 발생했습니다. 아이템들을 제대로 불러오지 못하고 화면을 재구성하는 데 실패하여 빈 화면을 보여주게 된 것입니다.
이 문제를 해결하기 위해 RecyclerView의 상태를 복원하는 방법을 적용했습니다. 이를 통해 화면이 빈 화면으로 나타나는 현상을 해결할 수 있었습니다. 다음은 해결 방법입니다.
해결 방법: RecyclerView 상태 복원
RecyclerView 상태를 복원하는 방법을 사용하여 문제를 해결했습니다. 상태를 복원하면 사용자가 상세 화면에서 돌아왔을 때 RecyclerView가 정확히 이전 상태를 유지할 수 있습니다.
1. 상태 저장을 위한 변수 추가:
- Fragment 클래스에 RecyclerView의 상태를 저장할 변수를 추가합니다.
private var recyclerViewState: Parcelable? = null
2. 상태 저장:
- Fragment가 중단되기 전에 RecyclerView의 상태를 저장합니다.
override fun onPause() {
super.onPause()
recyclerViewState = recyclerView.layoutManager?.onSaveInstanceState()
}
3. 상태 복원:
- Fragment가 다시 활성화될 때 저장된 상태를 복원합니다.
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
recyclerView.layoutManager?.onRestoreInstanceState(recyclerViewState)
}
5. 전체 수정된 코드:
class FavoriteListFragment : Fragment() {
private lateinit var photoAdapter: PhotoAdapter
private val favoriteListViewModel: FavoriteListViewModel by activityViewModels {
val application = requireActivity().application
val photoDao = FavoritePhotosDatabase.getDatabase(application).PhotoDao()
val retrofitService = RetrofitInstance.retrofitService
val unSplashDataSource = UnSplashDataSource(retrofitService)
val userDataSource = UserDataSource(photoDao)
val photoRepository = PhotoRepository(unSplashDataSource, userDataSource)
AppViewModelFactory(application, photoRepository)
}
private var recyclerViewState: Parcelable? = null
private var _binding: FragmentFavoriteListBinding? = null
private val binding get() = _binding!!
private lateinit var recyclerView: RecyclerView
private var isPass = false
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentFavoriteListBinding.inflate(inflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupRecyclerview()
setupObservers()
setupListeners()
}
private fun setupRecyclerview() {
photoAdapter = PhotoAdapter(favoriteListViewModel)
recyclerView = binding.recyclerView
val numberOfColumns = 2
val layoutManager =
StaggeredGridLayoutManager(numberOfColumns, LinearLayoutManager.VERTICAL).apply {
gapStrategy = StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS
}
recyclerView.layoutManager = layoutManager
binding.recyclerView.adapter = photoAdapter
}
private fun setupObservers() {
favoriteListViewModel.photos.observe(
viewLifecycleOwner
) { photos ->
photoAdapter.submitList(photos) {
if (recyclerViewState != null) {
recyclerView.layoutManager?.onRestoreInstanceState(recyclerViewState)
}
else {
recyclerView.scrollToPosition(0)
}
}
binding.tvEmpty.isVisible = photos.isEmpty()
}
}
private fun setupListeners() {
photoAdapter.setOnPhotoClickListener(object : PhotoAdapter.OnPhotoClickListener {
override fun onPhotoClick(photo: Photo) {
val intent = newPhotoDetail(requireContext(), photo)
startActivity(intent)
}
})
}
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
recyclerView.layoutManager?.onRestoreInstanceState(recyclerViewState)
}
override fun onResume() {
super.onResume()
if (isPass) {
isPass = false
return
}
favoriteListViewModel.onResumeScreen()
}
override fun onPause() {
super.onPause()
recyclerViewState = recyclerView.layoutManager?.onSaveInstanceState()
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
이 방법을 통해 RecyclerView의 상태를 저장하고 복원하여 상세 보기에서 돌아왔을 때 빈 화면이 나타나는 문제를 해결할 수 있습니다. 이로 인해 사용자 경험이 향상되었으며, 즐겨찾기 목록이 정상적으로 표시되었습니다.
반응형