일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- builderPattern
- Functional Programming
- Abstract Factory
- Design Pattern
- 빌터패턴
- factory method
- a
- 추상 팩토리
- F
- PrototypePattern
- ㅋㅁ
- 코틀린
- 디자인패턴 #
- 싱글톤
- r
- El
- 옵저버 패턴
- 추상팩토리패턴
- Singleton
- 프로토타입 패턴
- 팩토리 메소드
- ㅓ
- 함수형프로그래밍
- Kotlin
- Observer Pattern
- designPattern
- 디자인패턴
- Today
- Total
오늘도 더 나은 코드를 작성하였습니까?
android paging3 basic codelab 정리2 본문
Paging 라이브러리를 사용하면 ViewModel에 Flow<PagingData<Article>>을 대신 노출할 수 있습니다
PagingData는 로드된 데이터를 래핑하고 Paging 라이브러리가 추가 데이터를 가져올 시기를 결정하는 데 도움을 주는며 동일한 페이지를 두 번 요청하지 않도록 합니다.
PagingData를 구성하기 위해 PagingData를 앱의 다른 레이어에 전달하는 데 사용할 API에 따라 Pager 클래스의 여러 빌더 메서드 중 하나를 사용합니다.
- Kotlin Flow - Pager.flow 사용
- LiveData - Pager.liveData 사용
- RxJava Flowable - Pager.flowable 사용
- RxJava Observable - Pager.observable 사용
Repository
/**
* Repository class that mimics fetching [Article] instances from an asynchronous source.
*/
class ArticleRepository {
fun articlePagingSource() = ArticlePagingSource()
}
ViewModel
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)
}
PagingConfig
이 클래스는 로드 대기 시간, 초기 로드의 크기 요청 등 PagingSource에서 콘텐츠를 로드하는 방법에 관한 옵션을 설정합니다.
정의해야 하는 유일한 필수 매개변수는 각 페이지에 로드해야 하는 항목 수를 가리키는 페이지 크기입니다.
기본적으로 Paging은 로드하는 모든 페이지를 메모리에 유지합니다.사용자가 스크롤할 때 메모리를 낭비하지 않으려면 PagingConfig에서 maxSize 매개변수를 설정하세요.
기본적으로 Paging은 로드되지 않은 항목을 집계할 수 있고 enablePlaceholders 구성 플래그가 true인 경우 아직 로드되지 않은 콘텐츠의 자리표시자로 null 항목을 반환합니다. 이렇게 하면 Adapter에 Placeholder view를 표시할 수 있습니다
Codelab의 작업을 단순화하기 위해 enablePlaceholders = false를 전달하여 자리표시자를 사용하지 않음.
PagingSource를 만드는 방법을 정의하는 함수.
여기서는 ArticlePagingSource을 만들므로 Paging 라이브러리에 이 작업을 실행하는 방법을 알려주는 함수가 필요합니다
*PagingConfig.pageSize는 여러 화면의 항목이 포함될 만큼 충분히 커야 합니다. 페이지가 너무 작으면 페이지의 콘텐츠가 전체 화면을 가리지 않기 때문에 목록이 깜박일 수 있습니다. 페이지 크기가 클수록 로드 효율이 좋지만 목록이 업데이트될 때 지연 시간이 늘어날 수 있습니다. 첫 페이지에 다른 양의 항목을 로드하려면 PagingConfig.initialLoadSize를 사용하세요.
*기본 PagingConfig.maxSize에는 제한이 없으므로 페이지가 삭제되지 않습니다. 페이지를 삭제하려면 사용자가 스크롤 방향을 변경할 때 네트워크 요청이 너무 많이 발생하지 않도록 maxSize를 충분히 큰 수로 유지해야 합니다.
최솟값은 pageSize + prefetchDistance * 2입니다.
Pager
인스턴스의 출력 결과가 되도록 items를 업데이트합니다. Pager에 매개변수 두 개를 전달하면 됩니다.
- pageSize가 ITEMS_PER_PAGE이고 PlaceHolder가 사용 중지된 PagingConfig
- ArticlePagingSource의 인스턴스를 제공하는 PagingSourceFactory
주의사항
* pagingSourceFactory 람다는 PagingSource 인스턴스를 재사용할 수 없으므로 호출되는 경우 완전히 새로운 PagingSource를 반환해야 합니다.
* configuration 변경 / navigation 변경사항에도 페이징 상태를 유지하려면 androidx.lifecycle.viewModelScope를 전달하는 cachedIn() 메서드를 사용합니다.
* PagingData Flow와 함께 stateIn() 또는 sharedIn() 연산자를 사용하지 마세요. PagingData Flow는 콜드 상태가 아닙니다.
Flow에서 map 또는 filter와 같은 작업을 실행하는 경우 작업을 실행한 후 cachedIn을 호출하여 작업을 다시 트리거할 필요가 없도록 해야 합니다. 즉, 터미널 연산자로 cachedIn을 사용해야 합니다.
PagingData의 또 다른 유의 사항은 RecyclerView에 표시할 데이터에 관한 변경 가능한 업데이트 스트림이 포함된 독립적인 유형이라는 것입니다.
각 PagingData emit() 완전히 독립적이며 지원 PagingSource가 기본 데이터 세트 변경으로 인해 무효화되는 경우 단일 쿼리에 관해 여러 PagingData 인스턴스를 내보낼 수 있습니다. 따라서 PagingData의 Flows는 다른 Flows와 독립적으로 노출되어야 합니다.
PagingData Flow를 다른 Flows와 함께 사용하거나 결합하지 마세요.
emitted PagingData는 각각 독립적으로 사용되어야 합니다. 또한 shareIn 및 stateIn 같은 연산자를 PagingData Flows에 사용해서는 안 됩니다.
PagingDataAdapter
PagingData를 RecyclerView에 바인딩하려면 PagingDataAdapter를 사용하세요
PagingData 콘텐츠가 로드될 때마다 PagingDataAdapter에서 알림을 받은 다음 RecyclerView에 업데이트하라는 신호를 보냅니다.
PagingDataAdapter<ItemType, ViewHolder>(ARTICLE_DIFF_CALLBACK)
을 상속받아서 일반적인 ListAdapter / RecyclerViewAdapter 처럼 사용하면된다.
Activity
submitData() 함수를 통해 어뎁터에 데이터를 제공한다.
override fun onCreate(savedInstanceState: Bundle?) {
.
.
.
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
items.collectLatest {
articleAdapter.submitData(it)
}
}
}
.
.
.
}
UI에 Load 상태 표시하기.
Paging 라이브러리에서 UI에 표시할 항목을 더 많이 가져올 때는 사용자에게 더 많은 데이터를 가져오고 있다고 표시하는 것이 좋습니다. Paging 라이브러리는 CombinedLoadStates로 로드 상태에 간단하게 액세스하는 방법을 제공합니다.
CombinedLoadStates
데이터를 로드하는 Paging 라이브러리에 있는 모든 구성요소의 로드 상태를 설명합니다
여기서는 ArticlePagingSource의 LoadState에만 관심이 있으므로 주로 CombinedLoadStates.source 필드의 LoadStates 유형을 사용합니다
PagingDataAdapter.loadStateFlow를 통해 PagingDataAdapter를 통한 CombinedLoadStates에 액세스할 수 있습니다.
로드 상태를 설명하는 데 도움이 되는 세 가지 고유한 클래스는 CombinedLoadStates, LoadStates, LoadState입니다.
CombinedLoadStates안에 LoadStates 인스턴스가 있고, LoadStates에서 LoadState 인스턴스를 제공합니다.
CombinedLoadStates.source는 LoadStates 유형으로, 세 가지 유형의 LoadState 필드가 있습니다.
LoadState
- LoadStates.append: 사용자의 현재 위치 후에 가져오는 항목의 LoadState용입니다.
- LoadStates.prepend: 사용자의 현재 위치 전에 가져오는 항목의 LoadState용입니다.
- LoadState.refresh: 초기 로드의 LoadState용입니다.
LoadState
- LoadState.Loading: 항목을 로드하고 있습니다.
- LoadState.NotLoading: 항목을 로드하고 있지 않습니다.
- LoadState.Error: 로드 오류가 발생했습니다.
여기서는 LoadState가 LoadState.Loading인지만 중요합니다. ArticlePagingSource에 오류 사례가 포함되어 있지 않기 때문입니다.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
articleAdapter.loadStateFlow.collect {
binding.prependProgress.isVisible = it.source.prepend is Loading
binding.appendProgress.isVisible = it.source.append is Loading
}
}
}
}
'Android Jetpack Architecture > Paging3' 카테고리의 다른 글
android paging3 basic codelab 정리1 (0) | 2022.10.10 |
---|---|
REFRESH 배치 (0) | 2021.08.23 |
paging3 race conditions 처리와 remote keys 관리하기 (0) | 2021.08.19 |
RemoteMediator 구현하기 (0) | 2021.08.19 |
네트워크 및 데이터베이스의 페이징. (0) | 2021.08.19 |