본문 바로가기

TIL

TIL 72일차 - 최종프로젝트

class StratagemListActivity : ComponentActivity() {
    private val viewModel by lazy {
        ViewModelProvider(
            this, StratagemViewModel.StratagemViewModelFactory()
        )[StratagemViewModel::class.java]
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        viewModel.getStratagem()
        setContent {
            HellDivers2InfoTheme {
                Surface(
                    modifier = Modifier.fillMaxSize()
                ) {
                    StratagemListScreen(viewModel)
                }
            }
        }
    }

    @Composable
    fun StratagemListScreen(viewModel: StratagemViewModel) {
        val stratagemList by viewModel.stratagem.observeAsState()

        when {
            stratagemList?.isEmpty() == true -> LoadingScreen()
            else -> stratagemList?.get(0)?.data?.let { it -> StratagemList(it.map { it.name }) }
        }
    }

    @Composable
    fun StratagemData(viewModel: StratagemViewModel, index: Int = 0) {
        val stratagemList by viewModel.stratagem.observeAsState()

        when {
            stratagemList?.isEmpty() == true -> LoadingScreen()
            else -> stratagemList?.get(0)?.data?.get(index).let {
                if (it != null) {
                    StratagemDataListItem(it)
                }
            }
        }
    }

    @Composable
    fun StratagemDataListItem(item: StratagemResponse.Data) {
        Spacer(modifier = Modifier.height(8.dp))
        Text(text = "호출 시간: " + item.activation.toString())
        Spacer(modifier = Modifier.height(4.dp))
        Text(text = "쿨타임: " + item.cooldown.toString())
        Spacer(modifier = Modifier.height(4.dp))
        Row {
            Text(text = "호출 키: ")
            for (i in item.keys.indices) {
                when (item.keys[i]) {
                    "down" -> {
                        Icon(
                            imageVector = Icons.Filled.KeyboardArrowDown,
                            contentDescription = stringResource(id = R.string.down)
                        )
                    }
                    "up" -> {
                        Icon(
                            imageVector = Icons.Filled.KeyboardArrowUp,
                            contentDescription = stringResource(id = R.string.up)
                        )
                    }
                    "left" -> {
                        Icon(
                            imageVector = Icons.AutoMirrored.Filled.KeyboardArrowLeft,
                            contentDescription = stringResource(id = R.string.left)
                        )
                    }
                    "right" -> {
                        Icon(
                            imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight,
                            contentDescription = stringResource(id = R.string.right)
                        )
                    }
                }
            }
        }
    }

    @Composable
    fun StratagemList(names: List<String>) {
        LazyColumn(
            modifier = Modifier
                .padding(vertical = 34.dp, horizontal = 8.dp)
        ) {
            itemsIndexed(names) { index, name ->
                StratagemItem(name, index)
                Spacer(modifier = Modifier.height(8.dp))
            }
        }
    }

    @Composable
    private fun StratagemItem(name: String, index: Int = 0) {
        var expanded by rememberSaveable { mutableStateOf(false) }

        Row(
            modifier = Modifier
                .background(Color(0xFFFFE4E4))
                .padding(12.dp)
                .animateContentSize(
                    animationSpec = spring(
                        dampingRatio = Spring.DampingRatioMediumBouncy,
                        stiffness = Spring.StiffnessLow
                    )
                )
        ) {
            Column(
                modifier = Modifier
                    .weight(1f)
                    .padding(12.dp)
            ) {
                Text(
                    text = name,
                    style = MaterialTheme.typography.headlineMedium.copy(
                        fontWeight = FontWeight.Bold
                    )
                )
                if (expanded) {
                    StratagemData(viewModel, index)
                }
            }
            IconButton(onClick = { expanded = !expanded }) {
                Icon(
                    imageVector = if (expanded) {
                        Icons.Filled.KeyboardArrowUp
                    } else Icons.Filled.KeyboardArrowDown,
                    contentDescription = if (expanded) {
                        stringResource(id = R.string.show_less)
                    } else {
                        stringResource(id = R.string.show_more)
                    }
                )
            }
        }
    }

    @Composable
    fun LoadingScreen() {}

 

무료 API를 이용해 간단한 리스트를 만들어 보았다. 이전 Compose 테스트에서는 없었던 클릭 이벤트와 실제 데이터 사용을 추가했다.

@Composable
fun StratagemData(viewModel: StratagemViewModel, index: Int = 0) {
    val stratagemList by viewModel.stratagem.observeAsState()

    when {
        stratagemList?.isEmpty() == true -> LoadingScreen()
        else -> stratagemList?.get(0)?.data?.get(index).let {
            if (it != null) {
                StratagemDataListItem(it)
            }
        }
    }
}

 

기본적으로 데이터를 불러오는 작업과 UI 구성이 (거의)동시에 일어나기 때문에, 미처 데이터 값을 불러오지 못할 가능성이 있었다. 그래서 리스트의 값을 확인하는 로직과 LoadingScreen() (아직은 빈 화면) 을 추가했다. 이렇게 하면 데이터 로딩과 UI 렌더링이 더 안정적으로 처리될 것이다.

itemsIndexed(names) { index, name ->
    StratagemItem(name, index)
    Spacer(modifier = Modifier.height(8.dp))
}

 

itemsIndexed 함수를 사용해 indexOf를 사용할 때보다 더 효율적이고 직관적으로 인덱스를 가져올 수 있다.

'TIL' 카테고리의 다른 글

TIL 74일차 - 최종프로젝트  (0) 2024.07.04
TIL 73일차 - 최종프로젝트  (0) 2024.07.03
TIL 71일차 - 최종프로젝트  (0) 2024.07.01
TIL 70일차 - 최종프로젝트  (0) 2024.06.28
TIL 69일차 - 최종프로젝트  (0) 2024.06.27