[Android] Compose + Coroutine(API 호출) 간단하게 페이징 처리 구현하기

2025. 3. 17. 15:41· Development/Android
반응형

- 페이징 라이브러리를 사용한 것은 아니고, 파라미터로 page: Int를 보내고 response로 hasNext: Boolean을 수신받을 수 있는 형태의 api에서 페이징을 자체 코드로 간단하게 구현한 예시다.

상단 구성 

- Scaffold 구조로 상단에 TopAppBar를 가지고 내부 content로 리스트를 가지는 화면에서 페이징을 구성했다.

Scaffold(topBar = {
    TopAppBar(modifier = Modifier.padding(start = 12.dp),
        title = {
            Text()
        }, navigationIcon = {
            IconButton(modifier = Modifier
                .size(40.dp)
                .padding(8.dp),
                onClick = { finish() }) {}
        }, colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.White)
    )
}, content = {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.White)
            .systemBarsPadding()
    ) {
        MainList(it) //페이징처리가 적용될 Composable
    }
})

 

- MainList에는 4가지의 remember 변수가 선언된다.

val items = remember { mutableStateListOf<Item>() }
var hasNext by remember { mutableStateOf(true) }
val listState = rememberLazyListState()
val scope = rememberCoroutineScope()

- 리스트의 대상이 되는 객체를 담아둘 items와 마지막 페이지인지 검사하는 hasNext.


- hasNext의 경우 아직 api 호출을 안했으니 일단 무조건 다음 페이지가 있다고 가정한다.

- listState : LazyColumn / LazyRow에서 스크롤 상태를 기억하고 조작할 수 있도록 도와주는 LazyListState 객체를 생성

 

- 이를 통해 아이템 인덱스 및 스크롤 처리에 대한 접근이 가능하다. 또한 페이징 처리 시 list의 갱신 매개체가 된다.

 

- scope : Compose 내부에서 비동기 처리를 위해 Coroutine을 선언해 준다. 페이징 처리에 사용될 예정

페이징 처리 함수

- loadMore 함수가 페이징 처리의 역할을 한다. 해당 함수가 호출될 때마다 response로 서버로부터 마지막 페이지인지 여부를 알 수 있는 hasNext를 수신받는데, 이것이 false가 될 경우 더 이상 해당 함수의 로직을 진입하지 않는다.

fun loadMore() {
    if (!hasNext) return
    scope.launch {
        withContext(Dispatchers.IO) {
            isLoading = true
            val updated = try {
                GetApiTask(page).executeSync() ?: return@withContext
            } catch (e: Exception) {
                return@withContext
            }
            items.addAll(updated.data)
            hasNext = updated.hasNext
            isLoading = false
            page++
        }
    }
}

- IO dispatcher에서 API 호출이 진행되고 그 결과에 따라 아이템 리스트 목록이 추가되고, hasNext 및 page 값이 변동된다.

 

- isLoading의 경우 전역 변수로 선언되어 있는데 해당 변수는 API 호출 진행 중인 상태를 파악하여 중복으로 API가 호출되면서 발생하는 충돌 상황을 방지해 준다.

페이징 활용

LaunchedEffect(Unit) { loadMore() }

- LaunchedEffect는 컴포저블이 Composition 될 때 한 번 실행되는 비동기 블록이다.

- 컴포저블이 재구성(Recomposition)되어도 파라미터 변수 값이 변하지 않으면 재실행되지 않는다. 근데 Unit을 넣었으니 결국 컴포저블 생성 최초 1회만 생성되는 것이다.

 

- 그리고 그렇게 초기 구성된 아이템 리스트는 LazyColumn을 구성하게 된다.

if (items.isNotEmpty()) {
    LazyColumn(
        state = listState,
        contentPadding = contentPadding,
        modifier = Modifier
            .fillMaxSize()
            .padding(start = 4.dp)
    ) {
        items(items) {
            ItemHolder(item = it)
        }
    }
}

 

- 이제 listState의 변화를 체크하면서 마지막 리스트 요소에 도달할 때, 자동으로 loadMore() 함수를 호출하도록 구성해줘야 한다.

LaunchedEffect(listState) {
    snapshotFlow { listState.layoutInfo.visibleItemsInfo.lastOrNull() }.collect { lastVisibleItem ->
        if (lastVisibleItem != null && lastVisibleItem.index >= items.size - 3 && !isLoading) loadMore()
    }
}

- 마지막 아이템이 유효할 때, 현재 등록된 아이템의 3개 아이템 도달 전에 미리 로딩 상태를 체크하여 페이징 함수를 호출한다.

 

- snapshotFlow :Compose의 상태(State)가 변경될 때 Flow를 생성하는 기능을 제공한다.

 

- 이때 조건에 해당하는 flow를 collect 하여 조건 맞게 처리를 진행해 주면 된다.

 

- 정석적인 페이징 처리는 아니라서.. 오류 상황을 더 검토해 봐야겠지만 이처럼 간단한 구현 방식도 있다.

반응형
저작자표시 (새창열림)
'Development/Android' 카테고리의 다른 글
  • [Android] Fatal Exception: java.lang.IllegalStateExceptionObject is no longer valid to operate on. Was it deleted by another thread? Realm DB 관련 오류 대응
  • [Android] 구글 인앱 결제 처리 관련 코드를 Manager로 정리
  • [Android] vibrate() func deprecated 대응
  • [Android] Places Api (New)를 활용한 위치 검색 기능 구현 (feat. App Check, Compose UI)
SeungYong.Lee
SeungYong.Lee
반응형
SeungYong.Lee
Win-Dev
SeungYong.Lee
전체
오늘
어제
  • All (229)
    • Development (129)
      • Android (125)
      • iOS (0)
      • Flutter (4)
      • Backend (0)
    • Algorithm (5)
    • Knowledge (5)
      • IT (2)
      • Science (0)
      • ETC & Tip (3)
    • Today I Learn (28)
    • Coding Test (62)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

  • 안녕하세요. 반갑습니다 :)

인기 글

태그

  • Android
  • glance
  • hilt
  • dfs
  • Animation
  • HTTP
  • Collection
  • Java
  • 코틀린
  • 프로그래머스
  • Imageview
  • Flutter
  • 코딩테스트
  • Widget
  • 비동기처리
  • coroutine
  • exception
  • Kotlin
  • compose
  • Retrofit

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
SeungYong.Lee
[Android] Compose + Coroutine(API 호출) 간단하게 페이징 처리 구현하기
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.