개발하다가 서버로 파일 전송 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
}
}
}
보완은 좀 필요하겠으나. 일단 마무리..