개발하다가 서버로 파일 전송 API를 리스트 순서대로 동기 처리할 케이스가 생겨서 메모

private val failedFileList = mutableListOf<File>() // 실패 아이템 재전송 리스트
private var tryCount = 0 // 시도횟수
private var fileSendJob: Job? = null

fun sendMultipleFile(files: MutableList<File>) {
    fileSendJob?.cancel()
    fileSendJob = viewModelScope.launch {
        isLoadingLiveData.value = true // 로딩 시작
        for (eachFile in files) { // 동기로 동작시키므로 for문 처리
            val result = withContext(Dispatchers.IO) {
                runCatching {
                    fileSendUseCase.postPrescriptions(listOf(eachFile))
                }
            }

            result.onSuccess {
                    when(it) {
                        is CommonResponse.Success -> {
                            DLog.e("success response: ${it.data}")
                            if (failedFileList.contains(eachFile)) {
                                failedFileList.remove(eachFile)
                                tryCount--
                            }
                        }
                        is CommonResponse.Error -> {
                            DLog.e("error response: ${it.error.message}")
                            failedFileList.add(eachFile)
                        }
                    }

                }.onFailure {
                DLog.e("it: ${it.message}")
                failedFileList.add(eachFile)
            }
        }

        if (failedFileList.isNotEmpty() && tryCount < 3) {
            tryCount++
            sendMultipleFile(failedFileList)
        } else {
            if (failedFileList.isNotEmpty()) { // 최종적으로 실패한 아이템이 존재
                DLog.e("failedFileList: ${failedFileList.size}")
                successLiveData.value = Event(false)
                isLoadingLiveData.value = false // 로딩 종료
            } else { // 성공적으로 처리
                successLiveData.value = Event(true)
                isLoadingLiveData.value = false // 로딩 종료
            }
        }
    }

 

 

+ 비동기 처리

fun sendMultipleFile(files: MutableList<File>) {
    fileSendJob?.cancel()
    fileSendJob = viewModelScope.launch {
        isLoadingLiveData.value = true
        val deferredResults = files.map { eachFile ->
            async(Dispatchers.IO) {
                runCatching {
                    prescriptionUseCase.postPrescriptions(listOf(eachFile))                }
            }
        }

        val results = deferredResults.awaitAll()

        results.forEachIndexed { index, result ->
            val eachFile = files[index]
            result.onSuccess {
                when (it) {
                    is CommonResponse.Success -> {
                        DLog.e("success response: ${it.data}")
                        if (failedFileList.contains(eachFile)) {
                            failedFileList.remove(eachFile)
                            tryCount--
                        }
                    }
                    is CommonResponse.Error -> {
                        DLog.e("error response: ${it.error.message}")
                        failedFileList.add(eachFile)
                    }
                }
            }.onFailure {
                DLog.e("it: ${it.message}")
                failedFileList.add(eachFile)
            }
        }

        if (failedFileList.isNotEmpty() && tryCount < 3) {
            tryCount++
            sendMultipleFile(failedFileList)
        } else {
            if (failedFileList.isNotEmpty()) {
                DLog.e("failedFileList: ${failedFileList.size}")
                successLiveData.value = Event(false)
            } else {
                successLiveData.value = Event(true)
            }
            isLoadingLiveData.value = false
        }
    }
}


보완은 좀 필요하겠으나. 일단 마무리..

+ Recent posts