본문 바로가기
안드로이드/공부 및 정리

[Android]Android Rest 통신중 로딩 화면 만들기

by 디선 2024. 9. 18.

Compose 마이그레이션 및 로딩 상태 관리

Compose로 마이그레이션하며 기존과는 다른 방법으로 로딩 상태를 관리하는 방법을 시도해 보았다.

1. LoadingStateManager 생성

  • 전역 로딩 상태를 관리하는 LoadingStateManager를 생성한다.
object LoadingStateManager {
    private val _isLoading = MutableStateFlow(false)
    val isLoading: StateFlow<Boolean> = _isLoading.asStateFlow()

    fun isShow(isShow: Boolean) {
        _isLoading.value = isShow
    }
}
  • MutableStateFlow를 사용하여 로딩 상태를 관리하며, isShow 함수를 통해 로딩 상태를 업데이트한다.

2. Dialog로 로딩 화면 구성

  • Dialog를 이용해 기본 Compose 로딩 화면을 구성한다.
  • onDismissRequest는 현재 특별한 동작이 필요하지 않으므로 LoadingStateManager.isShow(false)로 설정했다.
@Composable
fun SplashDialogScreen() {
    val isLoading = LoadingStateManager.isLoading.collectAsState().value

    if (isLoading) {
        Dialog(onDismissRequest = { LoadingStateManager.isShow(false) }) {
            CircularProgressIndicator()
        }
    }
}
  • 로딩 상태가 활성화되면 Dialog가 나타나며, 비활성화 시 사라진다.

3. 최상위 Composable에 선언

  • 로딩 다이얼로그를 최상위 Composable에 선언한다.
  • MainActivity의 onCreate에서 로딩 화면을 추가했다.
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    enableEdgeToEdge()
    setContent {
        NewWeatherOpenApiTheme {
            Box(Modifier.safeDrawingPadding()) {
                InitScreen(locationDataManager)
                SplashDialogScreen()
            }
        }
    }
}
  • InitScreen과 함께 SplashDialogScreen을 추가하여 로딩 상태를 UI에서 관리할 수 있게 했다.

4. 로딩 상태 진입 및 종료

  • 로딩 시작 시: LoadingStateManager.isShow(true) 호출
  • 로딩 종료 시: LoadingStateManager.isShow(false) 호출
// 로딩 시작
LoadingStateManager.isShow(true)

// 로딩 종료
LoadingStateManager.isShow(false)

5. 로딩 화면 깜빡임 제거

  • 너무 빠른 로딩으로 인해 로딩 화면이 깜빡거리는 현상을 해결하기 위해 최소 로딩 시간을 설정했다.
private var isPendingToShow = false
private var pendingJob: Job? = null
private const val MIN_LOADING_TIME_MS = 100

private val coroutineScope = CoroutineScope(Dispatchers.Main)

fun isShow(isShow: Boolean) {
    if (isShow) {
        startLoadingDelay()
    } else {
        stopLoading()
    }
}

private fun startLoadingDelay() {
    isPendingToShow = true
    pendingJob?.cancel()

    pendingJob = coroutineScope.launch {
        delay(MIN_LOADING_TIME_MS.toLong())
        if (isPendingToShow) {
            _isLoading.value = true
        }
    }
}

private fun stopLoading() {
    isPendingToShow = false
    pendingJob?.cancel()

    _isLoading.value = false
}
  • 최소 로딩 시간을 0.1초로 설정했다.
  • pendingJob을 사용해 딜레이가 실행되는 동안 isPendingToShowfalse로 변경되면 _isLoadingtrue로 설정하지 않도록 했다.
반응형