마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

Paging3 와 Navigation 을 함께 사용할 때, Fragment 전환시에도 페이징 데이터를 유지하는 방법

0 추천

안녕하세요!

더 좋은 방법이 있는지 모르겠어서 문의드립니다 ㅜ

제목 그대로,

Paging3 와 Navigation 을 함께 사용할 때, Fragment 전환시에도 페이징 데이터를 유지하는 방법의

best practice 가 궁금합니다.

 

Single Activity 에 Multi Fragment 구조로 되어 있고요.

Navigation 라이브러리를 사용하고 있습니다.

문제는 Navigation 은 fragment 전환시에 replace 를 하기에

항상 Fragment Create/Destroy 가 일어나는데요.

그러다보니 viewModel 의 scope 를 Fragmet 로 하면,

다시 페이지데이터가 있는 Fragment 진입시에 원격지 API 를 호출하는 이슈입니다.

 

이를 해결하기 위해 현재

Activity scope 로 ViewModel 을 사용하고 있습니다. (by activityViewModels())

이 방법이 올바른 방법인지 궁금합니다.

아래는 해당 ViewModel 일부 코드입니다

 

Fragment scope 로는 뭔 짓을 해도 안되더라고요.

cachedIn(viewModelScope) 도 결국엔 VIewModel 이 Fragment 와 lifecycle이 같은데,

이 Fragment 가 재생성 되어버리니.. ViewModel 의 데이터가 모두 초기화됩니다..

답변 기다리겠습니다.

감사합니다.

 

@HiltViewModel
class MatchesViewModel @Inject constructor(
    private val matchUseCase: MatchUseCase
) : ViewModel() {
    private val _matchesFlow = MutableStateFlow<PagingData<Match>>(PagingData.empty())
    val matchesFlow = _matchesFlow.asStateFlow()

    private val _matchOutputRemoteFlow = MutableSharedFlow<RemoteState<MatchOutput>>()
    val matchOutputRemoteFlow = _matchOutputRemoteFlow.asSharedFlow()

    private val _hiddenMatchNosFlow = MutableStateFlow<List<Long>>(emptyList())
    val hiddenMatchNosFlow = _hiddenMatchNosFlow.asStateFlow()

    init {
        // 새로고침 시 중복 호출을 방지하기 위해 이 곳에서 수행
        fetchMatches()
    }

    private fun fetchMatches() {
        viewModelScope.launch {
            matchUseCase.fetchMatches(pageSize = 4)
                .cachedIn(viewModelScope)
                .combine(_hiddenMatchNosFlow) { pagingData, hiddenMatchNos ->
                    hiddenMatchNos.fold(pagingData) { acc, matchNo ->
                        filterHiddenMatch(acc, matchNo)
                    }
                }
                .collectLatest { pagingData ->
                    _matchesFlow.update { pagingData }
                }
        }
    }
}

 

lhs314390 (160 포인트) 님이 2023년 11월 8일 질문

1개의 답변

+1 추천
 
채택된 답변
Navigation component에 보시면 상태저장/복구 옵션이 있습니다. 아래 링크를 참조하세요.
https://developer.android.com/guide/navigation/backstack/multi-back-stacks#nav-xml

app:restoreState

그리고 backstack을 클리어히지 않았다면 ViewModel도 살아 있습니다. ViewModel이 초기화 된다는 건  backstack에서 제거했기 때문에 그런 것 같습니다. 네비게이션을 사용할 때 backstack 처리를 어떻게 하고 있는지 확인해 보세요.
spark (227,530 포인트) 님이 2023년 11월 8일 답변
lhs314390님이 2023년 11월 9일 채택됨
감사합니다! 제가 잘못 알고 있었네요.
backstack 에 있는 Fragment 및 ViewModel 은 파괴되는게 아니네요.

제가 setOnItemSelectedListener 리스너로
탭 이동시마다 saveState = false 로 이동하는 부분이 있었습니다.
...