[안드로이드 Jetpack Compose UI] LazyRow를 사용해서 RecyclerView 구현하기

2024. 3. 18. 11:30·안드로이드/Compose UI
반응형

안녕하세요. 이번 시간에는 안드로이드 Jetpack Compose에서 LazyRow를 사용해 가로 방향으로 무한 스크롤이 되면서 메모리 최적화 기능이 적용된 RecyclerView를 구현하겠습니다. 기존의 안드로이드 레이아웃 XML 방식을 사용해 보신 분들이라면 RecyclerView를 만들 때, 필요한 사전작업이 많았다는 걸 아실 텐데요. Compose로 넘어와서는 상당히 간단하게 구현할 수 있게 됐습니다. Compose에서 제공하는 LazyRow를 사용하면 가로 방향으로 무한 스크롤이 되는 RecyclerView를 만들 수 있습니다. 그럼 지금부터 코드와 함께 예제를 보여드리겠습니다.

안드로이드 Jetpack Compose에서 구현한 Horizontal RecyclerView
안드로이드 Jetpack Compose에서 구현한 Horizontal RecyclerView

1. LazyRow를 사용해서 RecyclerView 만들기

LazyRow는 항목을 가로로 배치하고, 사용자가 스크롤을 통해 양옆으로 탐색할 수 있게 해 줍니다. XML 기반의 RecyclerView에서는 Adapter 클래스가 추가로 필요했지만, Compose의 LazyRow를 사용하면 가로 방향으로 무한 스크롤이 가능한 RecyclerView를 손쉽게 구현할 수 있으며, Compose의 itemsIndexed 함수를 사용해 각 항목에 고유한 인덱스를 부여할 수 있습니다. 이를 통해 정보를 제공하는 동시에 메모리 사용을 최적화할 수 있습니다.

@Composable
fun CustomVerticalRecyclerView(users: List<ProfileEntity>) {
    LazyRow(
        modifier = Modifier.fillMaxSize(),
        horizontalArrangement = Arrangement.spacedBy(8.dp),
        content = {
            itemsIndexed(users) { index, user ->
                CustomUserProfile(
                    id = user.id,
                    name = user.name,
                    age = user.age,
                    nickName = user.nickName,
                    hobby = user.hobby
                )
            }
        })
}

@Composable
fun CustomUserProfile(id: Int, name: String, age: Int, nickName: String, hobby: String) {
    Card(
        modifier = Modifier
            .padding(4.dp)
            .wrapContentWidth()
            .height(130.dp)
            .wrapContentWidth(Alignment.Start),
        shape = RoundedCornerShape(15.dp),
        elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
        colors = CardDefaults.cardColors(
            containerColor = Color(0xFFECEFF1),
        )
    ) {
        Row(
            modifier = Modifier
                .fillMaxHeight()
                .padding(top = 12.dp, bottom = 12.dp, start = 12.dp, end = 30.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            // 프로필 이미지나 아이콘을 여기에 넣을 수 있습니다.
            Icon(
                imageVector = Icons.Filled.AccountCircle,
                contentDescription = "Profile",
                modifier = Modifier
                    .size(60.dp)
                    .padding(4.dp),
                tint = Color.Gray
            )

            Spacer(modifier = Modifier.width(12.dp))

            Column {
                Text(
                    text = "# $id",
                    style = TextStyle(
                        color = Color.Black,
                        fontSize = 22.sp,
                        fontWeight = FontWeight.Bold
                    )
                )

                Spacer(modifier = Modifier.height(4.dp))

                Text(
                    text = "$name a.k.a $nickName",
                    style = TextStyle(
                        color = Color.Black,
                        fontSize = 18.sp,
                        fontWeight = FontWeight.Bold
                    )
                )

                Spacer(modifier = Modifier.height(4.dp))

                Text(
                    text = "Age: $age",
                    style = TextStyle(
                        color = Color.DarkGray,
                        fontSize = 14.sp
                    )
                )

                Spacer(modifier = Modifier.height(4.dp))

                Text(
                    text = "Hobby: $hobby",
                    style = TextStyle(
                        color = Color.DarkGray,
                        fontSize = 14.sp
                    )
                )
            }
        }
    }
}

2. LazyRow 사용하기

데이터 모델링은 ViewModel에서 추가했습니다. 서버 API 통신을 해서 데이터를 불러오는 것처럼 재현하기 위해서 generateDummyProfiles 함수를 통해 무작위 프로필 데이터를 생성하며, 이 데이터는 Composable 함수에서 LazyRow를 구성하는 데 사용했습니다.

data class ProfileEntity(
    val id: Int,
    val name: String,
    val age: Int,
    val nickName: String,
    val hobby: String,
)

@HiltViewModel
class HorizontalRecyclerViewViewModel @Inject constructor(
    savedStateHandle: SavedStateHandle,
) : ViewModel() {
    val users = mutableStateOf<List<ProfileEntity>>(generateDummyProfiles())
    private fun generateDummyProfiles(): List<ProfileEntity> {
        val names = listOf(
            "John", "Emily", "Michael", "Rachel", "Sophie",
            "Daniel", "Laura", "David", "Sarah", "Chris",
            "Anna", "Max", "Julia", "Robert", "Lisa",
            "James", "Maria", "Paul", "Alice", "Tom"
        )
        val nickNames = listOf(
            "Skywalker", "Ranger", "Phoenix", "Shadow", "Maverick",
            "Viper", "Wizard", "Rogue", "Spartan", "Hunter"
        )
        val hobbies = listOf(
            "Reading", "Gaming", "Traveling", "Cooking", "Photography",
            "Painting", "Music", "Hiking", "Cycling", "Swimming"
        )

        return List(5000) { index ->
            ProfileEntity(
                id = index,
                name = names.random(),
                nickName = nickNames.random(),
                hobby = hobbies.random(),
                age = (18..60).random()
            )
        }
    }
}


ViewModel에서 생성한 데이터를 HorizontalRecyclerViewScreen 컴포저블에서 가져와 사용합니다. UI로직과 데이터 처리를 분리한 구조이기 때문에 코드의 가독성과 관리를 향상하는데 도움을 주는 장점이 있습니다. 그리고 ViewModel에서 데이터를 관리하면 안드로이드의 라이프사이클을 인식하므로 화면 회전에도 데이터 상태를 유지할 수 있습니다.

@Composable
fun HorizontalRecyclerViewScreen(
    mainNavController: NavHostController,
    viewModel: HorizontalRecyclerViewViewModel
) {
    val users by remember { viewModel.users }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(top = 10.dp)
    ) {
        Spacer(modifier = Modifier.height(10.dp))

        Text(
            text = "item's count : ${users.size}",
        )

        Spacer(modifier = Modifier.height(10.dp))

        CustomVerticalRecyclerView(
            users = users
        )
    }
}

3. LazyRow에서 itemIndexed 사용하기

LazyRow의 itemIndexed 함수를 사용하면, 각 항목에 고유 인덱스를 부여할 수 있습니다. 인덱스와 각 아이템의 항목을 람다의 인자로 전달받을 수 있기 때문에 데이터 바인딩하는데 무척 편리합니다. 그래서 실무에서는 itemIndexed를 많이 사용하게 되는데, 상황에 맞춰서 item, items 함수를 사용할 때도 편리합니다.

4. 정리

안드로이드 Jetpack Compose의 LazyRow를 이용한 RecyclerView 구현은 기존 XML 방식에 비해서 코드가 간결하여 간단하게 개발할 수 있습니다. 또한, 아이템 간의 간격을 추가할 때도 Arrangement.spacedBy() 함수를 통해 설정할 수 있으며 별도의 Adapter 클래스가 필요하지 않은 것도 편하게 느껴집니다.

이 글을 통해 안드로이드 Jetpack Compose UI에서 LazyRow를 활용한 RecyclerView 구현 방법을 이해하고, 여러분의 프로젝트에 적용하는데 도움이 되기를 바랍니다.

저작자표시 비영리 변경금지

'안드로이드 > Compose UI' 카테고리의 다른 글

[안드로이드 Jetpack Compose UI] Row를 사용해서 HorizontalScrollView 구현하기  (0) 2024.03.17
[안드로이드 Jetpack Compose UI] LazyColumn을 사용해서 무한 스크롤 뷰 만들기  (0) 2024.03.15
[안드로이드 Jetpack Compose UI] Column을 사용해서 VerticalScrollView 구현하기  (0) 2024.03.14
[안드로이드 Jetpack Compose UI] TabPager 구현하기  (0) 2024.03.13
[안드로이드 Jetpack Compose UI 시리즈] ViewPager 구현하기  (0) 2024.03.12
'안드로이드/Compose UI' 카테고리의 다른 글
  • [안드로이드 Jetpack Compose UI] Row를 사용해서 HorizontalScrollView 구현하기
  • [안드로이드 Jetpack Compose UI] LazyColumn을 사용해서 무한 스크롤 뷰 만들기
  • [안드로이드 Jetpack Compose UI] Column을 사용해서 VerticalScrollView 구현하기
  • [안드로이드 Jetpack Compose UI] TabPager 구현하기
코딩덕
코딩덕
안드로이드, 리액트 등의 개발 노하우와 최신 AI 기술을 다루는 기술 블로그입니다. 실무 중심의 경험을 바탕으로 마주한 문제와 해결 과정을 체계적으로 기록하며, 개발자에게 실질적으로 도움 되는 프로그래밍 팁과 인사이트를 쉽고 명확하게 공유하고자 합니다.
  • 코딩덕
    개발자가 들려주는 IT 이야기
    코딩덕
  • 전체
    오늘
    어제
    • 분류 전체보기 (66)
      • 안드로이드 (62)
        • 멀티 모듈 (11)
        • 클린 아키텍처 (11)
        • 트러블 슈팅 (5)
        • 코틀린 (3)
        • 코루틴 (2)
        • Compose (1)
        • Compose UI (6)
        • Compose Dialog (8)
        • Compose Paging3 (11)
        • Compose State (2)
        • Util (1)
      • Github (3)
        • PR Template (2)
        • AI Code Review (1)
      • 리액트 (1)
        • NextJs (1)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    sealed class
    Github
    Jetpack Compose
    코틀린
    MutableState
    recyclerview
    Usecase
    Gradle
    jsonadapter
    LazyRow
    안드로이드
    데이터 레이어
    ViewModel
    pager
    클린 아키텍처
    트러블슈팅
    paging3
    Clean Architecture
    enum class
    Dialog
    pr template
    UI Layer
    ai code review
    multi module
    ScrollView
    dynamic json
    flow
    코루틴
    멀티 모듈
    OnBackPressedDispatcher
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
코딩덕
[안드로이드 Jetpack Compose UI] LazyRow를 사용해서 RecyclerView 구현하기
상단으로

티스토리툴바