Android(Kotlin)

Paging Advanced

----___<<<<< 2022. 12. 26. 23:15

 

Paging을 공부하다 보면 나오는 remoteMediator입니다.

 

1. remoteMediator를 왜쓰는가

 

This time, we’re dialing things up a notch. Till now we’ve been pulling our data directly from the network which works only in the best of circumstances. We may sometimes be on a slow internet connection, or have lost connection entirely. Even if our connection is good, we certainly don’t want our app to be a data hog as re-fetching data every time you navigate into a screen is wasteful.

The solution to these issues is to have a local cache we pull from, and refresh only when necessary. Updates to the cache should always hit the cache first, and then be propagated to the ViewModel. This way the local cache is the single source of truth. Conveniently for us, the Paging Library has this covered with a little help from the Room library! Let’s get into it!

 

네트워크 환경이 불안정할 때나 매번 데이터를 로드하는건 낭비니깐 remoteMediator를 사용해서 Room에 저장해놓고 씁니다.

 

 

2. 어떻게 쓰는가

 

구성항목을 일부 보겠습니다.

 

RemoteMediator의 기본 역할은 Pager가 데이터를 모두 사용했거나 기존 데이터가 무효화되었을 때 네트워크에서 더 많은 데이터를 로드하는 것입니다. RemoteMediator는 로드 동작을 정의하기 위해 재정의해야 하는 load() 메서드를 포함합니다.

일반적인 RemoteMediator 구현에는 다음 매개변수가 포함됩니다.

  • query: 백엔드 서비스에서 검색할 데이터를 정의하는 쿼리 문자열
  • database: 로컬 캐시의 역할을 하는 Room 데이터베이스
  • networkService: 백엔드 서비스의 API 인스턴스

 

@OptIn(ExperimentalPagingApi::class)
class ExampleRemoteMediator(
  private val query: String,
  private val database: RoomDb,
  private val networkService: ExampleBackendService
) : RemoteMediator<Int, User>() {
  val userDao = database.userDao()

  override suspend fun load(
    loadType: LoadType,
    state: PagingState<Int, User>
  ): MediatorResult {
    // ...
  }
}

 

load() 메서드의 반환 값은 MediatorResult 객체입니다. MediatorResult MediatorResult.Error(오류 설명 포함) 또는 MediatorResult.Success(로드할 데이터가 더 있는지 여부를 나타내는 신호 포함)일 수 있습니다.

 

  • 로드가 성공적이고 수신된 항목 목록이 비어 있지 않으면 목록 항목을 데이터베이스에 저장하고 MediatorResult.Success(endOfPaginationReached = false)를 반환합니다. 데이터가 저장된 후에는 데이터 소스를 무효화하여 페이징 라이브러리에 새 데이터를 알립니다.
  • 로드가 성공적이고 수신된 항목 목록이 비어 있거나 마지막 페이지 색인인 경우 MediatorResult.Success(endOfPaginationReached = true)를 반환합니다. 데이터가 저장된 후에는 데이터 소스를 무효화하여 페이징 라이브러리에 새 데이터를 알립니다.
  • 요청에서 오류가 발생한 경우 MediatorResult.Error를 반환합니다.

 

RemoteMediator 구현은 또한 initialize() 메서드를 재정의하여 캐시된 데이터가 오래되었는지 점검하고 원격 새로고침을 트리거할지 결정할 수 있습니다. 이 메서드는 로드하기 전에 실행되므로 로컬 또는 원격 로드를 트리거하기 전에 데이터베이스를 조작할 수 있습니다(예: 기존 데이터 삭제).

initialize()는 비동기 함수이므로 데이터를 로드하여 데이터베이스에 있는 기존 데이터의 관련성을 확인할 수 있습니다. 가장 일반적인 사례는 캐시된 데이터가 특정 기간에만 유효한 경우입니다. RemoteMediator는 만료 기간이 지났는지 확인할 수 있으며, 이런 경우 페이징 라이브러리는 데이터를 완전히 새로고침해야 합니다. initialize() 구현은 다음과 같이 InitializeAction을 반환해야 합니다.

  • 로컬 데이터를 완전히 새로고침해야 하는 경우 initialize()는 InitializeAction.LAUNCH_INITIAL_REFRESH를 반환해야 합니다. 그러면 RemoteMediator가 원격으로 새로고침을 실행하여 데이터를 완전히 새로고침합니다. APPEND 또는 PREPEND의 원격 로드는 REFRESH 로드가 성공할 때까지 기다린 후에 진행됩니다.
  • 로컬 데이터를 새로고침할 필요가 없는 경우 initialize()가 InitializeAction.SKIP_INITIAL_REFRESH를 반환해야 합니다. 그러면 RemoteMediator가 원격 새로고침을 건너뛰고 캐시된 데이터를 로드합니다.
override suspend fun initialize(): InitializeAction {
  val cacheTimeout = TimeUnit.MILLISECONDS.convert(1, TimeUnit.HOURS)
  return if (System.currentTimeMillis() - db.lastUpdated() >= cacheTimeout)
  {
    // Cached data is up-to-date, so there is no need to re-fetch
    // from the network.
    InitializeAction.SKIP_INITIAL_REFRESH
  } else {
    // Need to refresh cached data from network; returning
    // LAUNCH_INITIAL_REFRESH here will also block RemoteMediator's
    // APPEND and PREPEND from running until REFRESH succeeds.
    InitializeAction.LAUNCH_INITIAL_REFRESH
  }
}

 

 

- 참조

 

https://medium.com/androiddevelopers/going-deeper-paging-from-network-and-database-in-the-mad-skills-series-9c98250b246b

 

Going deeper, paging from network and database in the MAD skills series

Welcome back! In the last episode, we integrated a Pager into our ViewModel and used it to populate the UI using a PagingDataAdapter. We…

medium.com

 

 

https://developer.android.com/topic/libraries/architecture/paging/v3-network-db?hl=ko 

 

네트워크 및 데이터베이스의 페이지  |  Android 개발자  |  Android Developers

네트워크 및 데이터베이스의 페이지 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 네트워크 연결이 불안정하거나 사용자가 오프라인 상태일 때 앱을 사용

developer.android.com

 

https://www.daniweb.com/programming/mobile-development/tutorials/537754/android-native-how-to-use-remotemediator

 

Android Native - How to use RemoteMediator

## Introduction ## The Android Paging 3 library can operate in two modes, with an offline Room database as a source of truth or without one. In this tutorial, ...

www.daniweb.com

 

https://www.charlezz.com/?p=44568 

 

안드로이드 Paging3 컴포넌트 정복하기 – Part2 (네트워크에서의 페이징과 로컬 데이터 캐싱) | 찰

안드로이드 Paging3 컴포넌트 정복하기 - Part2 지난 Part1 에서는 Paging3 전반적인 내용과 PagingSource를 통해 네트워크로부터 페이징 된 데이터를 로드하고 화면에 나타내는 방법에 대해서 살펴보았다.

www.charlezz.com

 

https://developer.android.com/codelabs/android-paging#3

 

Android Paging 고급 Codelab  |  Android Developers

이 Codelab에서는 Paging 라이브러리를 포함하도록 샘플 앱을 수정하여 앱의 메모리 공간을 줄입니다.

developer.android.com

 

'Android(Kotlin)' 카테고리의 다른 글

local.properties  (0) 2023.01.17
Unix Time to SimpleDataFormat  (0) 2023.01.09
Room SQLCipher  (0) 2022.12.21
StateFlow / SharedFlow  (0) 2022.12.15
Hot Stream / Cold Stream  (0) 2022.12.15