본문 바로가기
Kotlin

[Paging] ViewModel에서 PagingData 요청 및 캐시

by 명훈스토리 2023. 2. 20.
SMALL

컴파일 오류를 해결하기 전에 ViewModel을 살펴보겠다.

 

class ArticleViewModel(...) : ViewModel() {

    val items: StateFlow<List<Article>> = ...
}

ViewModel에 Paging 라이브러리를 통합하기 위해 items의 반환 유형을 StateFlow<List<Ariticle>>에서 Flow<PagingData<Article>>로 변경한다. 이렇게 하려면 먼저 ITEMS_PER_PAGE라는 비공개 상수를 파일 상단에 추가한다.

 

private const val ITEMS_PER_PAGE = 50

class ArticleViewModel {
    ...
}

다음으로 Pager 인스턴스의 출력 결과가 되도록 items를 업데이트한다. Pager에 매개변수 두 개를 전달하면 된다.

 

- pageSize가 ITEMS_PER_PAGE이고 자리표시자가 사용 중지된 PagingConfig

- 방금 만든 ArticlePagingSource의 인스턴스를 제공하는 PagingSourceFactory

 

class ArticleViewModel(...) : ViewModel() {

   val items: Flow<PagingData<Article>> = Pager(
        config = PagingConfig(pageSize = ITEMS_PER_PAGE, enablePlaceholders = false),
        pagingSourceFactory = { repository.articlePagingSource() }
    )
        .flow
        ...
}

※ pagingSourceFactory 람다는 PagingSource 인스턴스를 재사용할 수 없으므로 호출되는 경우 항상 완전히 새로운 PagingSource를 반환해야 한다.

 

이제 구성 또는 탐색 변경사항에도 페이징 상태를 유지하려면 androidx.lifecycle.viewModelScope를 전달하는 cachedIn() 메소드를 활용한다.

 

※ PagingData Flow와 함께 stateIn() 또는 sharedIn() 연산자를 사용하면 안 된다. PagingData Flow는 콜드 상태가 아니다. Flow에서 map 또는 filter와 같은 작업을 실행하는 경우 작업을 실행한 후 cachedIn을 호출하여 작업을 다시 트리거할 필요가 없도록 해야 한다. 즉, 터미널 연산자로 cachedIn을 사용해야 한다.

 

위 변경을 완료하면 ViewModel이 다음과 같이 표시된다.

 

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.cachedIn
import com.example.android.codelabs.paging.data.Article
import com.example.android.codelabs.paging.data.ArticleRepository
import com.example.android.codelabs.paging.data.ITEMS_PER_PAGE
import kotlinx.coroutines.flow.Flow

private const val ITEMS_PER_PAGE = 50

class ArticleViewModel(
    private val repository: ArticleRepository,
) : ViewModel() {

    val items: Flow<PagingData<Article>> = Pager(
        config = PagingConfig(pageSize = ITEMS_PER_PAGE, enablePlaceholders = false),
        pagingSourceFactory = { repository.articlePagingSource() }
    )
        .flow
        .cachedIn(viewModelScope)
}

PagingData의 또 다른 유의 사항은 RecyclerView에 표시할 데이터에 관한 변경 가능한 업데이트 스트림이 포함된 독립적인 유형이라는 것이다. 각 PagingData 내보내기는 완전히 독립적이며 지원 PagingSource가 기본 데이터 세트 변경으로 인해 무효화되는 경우 간일 쿼리에 관해 여러 PagingData 인스턴스를 내보낼 수 있다. 따라서 PagingData의 Flows는 다른 Flows와 독립적으로 노출되어야 한다.

 

※ PagingData Flow를 다른 Flows와 함께 사용하거나 결합하지 않아야 한다. 내보낸 PagingData는 각각 독립적으로 사용되어야 한다. 또한, sharedIn 및 stateIn 같은 연산자를 PagingData Flows에 사용해서는 안 된다.

LIST

'Kotlin' 카테고리의 다른 글

[Paging] UI에서 PagingData 사용  (0) 2023.02.20
[Paging] PagingData를 사용하도록 어댑터 설정  (0) 2023.02.20
[Paging] UI용 PagingData 생성  (0) 2023.02.07
[Paging] Paging 사용법  (0) 2023.02.05
[Paging] Paging이란?  (0) 2023.02.03

댓글