본문 바로가기

안드로이드/Compose Paging3

[안드로이드 Jetpack Compose Paging3 시리즈] LazyColumn 구현 #4


1. PagingData, LazyColumn을 사용한 무한 스크롤 리스트 구현

안녕하세요. 지난 시간에는 안드로이드 Jetpack Compose의 Paging3 라이브러리를 사용하기 위해 PagingSource와 PagingConfig를 활용하여 네트워크에서 데이터를 페이징 처리하는 방법을 살펴보았습니다. 이번 포스팅에서는 안드로이드 Jetpack Compose의 LazyColumn을 사용해서 Paging3 라이브러리에서 불러온 데이터를 사용자에게 보여주는 기능을 구현하겠습니다.

Paging3, LazyColumn을 통해 무한스크롤 리스트 UI를 구현한 모습
Paging3, LazyColumn을 통해 무한스크롤 리스트 구현

1-1. LazyColumn 개념

LazyColumn은 Jetpack Compose에서 제공하는 컴포저블 함수로, 화면에 보이는 부분만 렌더링 하기 때문에 RecyclerView와 마찬가지로 리스트를 효율적으로 표시할 수 있게 해주는 컴포넌트입니다. Paging3 라이브러리를 사용해서 RecyclerView를 구현하려면 layout, Adapter 등의 선행 작업이 필요했지만, Jetpack Compose의 LazyColumn은 이러한 선행 작업이 필요 없어서 편한 장점이 있습니다. 

1-2. PagingData와 LazyColumn 연동

Paging3 라이브러리와 Jetpack Compose를 함께 사용할 때는, collectAsLazyPagingItems() 확장 함수를 사용하여 PagingData를 LazyPagingItems로 변환한 후, 이를 LazyColumn에서 사용할 수 있습니다. RecyclerView를 구현할 때보다 코드가 엄청 줄어든 것을 확인할 수 있습니다.

@Composable
fun MovieListScreen(
    mainNavController: NavHostController,
    viewModel: MovieListViewModel
) {
    val movies = viewModel.movies.collectAsLazyPagingItems()
    MovieListScreen(mainNavController, movies)
}
@Composable
fun MovieListScreen(
    mainNavController: NavHostController,
    movies: LazyPagingItems<MovieEntity>
) {
    val favoriteIcon = drawable.ic_favorite_fill_white // drawable.ic_favorite_border_white

    Scaffold(
        floatingActionButton = {
            FloatingActionButton(onClick = { /*TODO*/ }) {
                Image(
                    painter = painterResource(id = favoriteIcon),
                    contentDescription = null,
                    Modifier.size(24.dp),
                )
            }
        },
        topBar = {
            TopAppBar(
                title = { Text(text = "영화 목록") },
                navigationIcon = {
                    IconButton(onClick = { mainNavController.popBackStack() }) {
                        Icon(imageVector = Icons.Default.ArrowBack, contentDescription = null)
                    }
                }
            )
        }
    ) { paddingValues ->
        LazyColumn(
            Modifier.padding(paddingValues),
            userScrollEnabled = true,
        ) {
            items(movies.itemCount) { index ->
                val movie = movies[index]
                MovieItem(movie!!, ImageSize.getImageFixedSize())
            }
        }
    }
}
@Composable
private fun MovieItem(
    movie: MovieEntity,
    imageSize: ImageSize,
    onMovieClick: (movieId: Int) -> Unit = {}
) {
    SubcomposeAsyncImage(
        model = movie.image,
        loading = { MovieItemPlaceholder() },
        error = { MovieItemPlaceholder() },
        contentDescription = null,
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .padding(3.dp)
            .size(imageSize.width, imageSize.height)
            .clickable { onMovieClick(movie.id) }
            .clip(RoundedCornerShape(2))
    )
}

2. PagingData, LazyColumn 정리

이번 포스팅에서는 안드로이드 Jetpack Compose Paging3 라이브러리부터 불러온 데이터를 LazyColumn을 사용해서 무한 스크롤로 보여주는 UI를 구현했습니다. Paging3 라이브러리를 사용해서 Jetpack Compose로 무한 스크롤을 구현할 때는 Xml의 RecyclerView로 구현할 때 보다 코드량이 엄청 줄어들게 됩니다. Paging3 라이브러리의 메커니즘만 이해하고 있으면 비교적 간단하게 구현되는 것 같습니다.

다음 포스팅에서는 LazyVerticalGrid를 사용해서 UI를 좀 더 이쁘게 꾸며보고, 영화를 클릭했을 때 클린 아키텍처 시리즈에서 구현한 영화 상세 화면으로 이동하는 기능을 구현하겠습니다.