π When building an app that involves network operations, such as transferring funds, itβs crucial to prevent the user from triggering the same operation multiple times unintentionally. This could lead to duplicate transactions or other unwanted effects. Hereβs a straightforward strategy using Kotlin Coroutines within a ViewModel to ensure that the transfer operation can only be executed once at a time.
Key Approach:
- π Job Control: Utilize a nullable Job variable to keep track of the ongoing transfer task. By setting this variable, you can easily check whether a previous task is still running.
Implementation Steps:
- Handle Results: Upon completion or failure, update the UI state with the results or error message, then reset makeTransferJob to null to allow new operations. β
- Initialize a Job Variable: Create a nullable Job variable, makeTransferJob, which will control the execution flow. π
- Check Job Status: Before launching the coroutine for a new transfer, check if makeTransferJob is null. If not, it means a transfer is already in progress, and the function will return early. β±οΈ
- Execute Transfer: Launch a coroutine in viewModelScope to perform the transfer. Update the UI state to indicate loading at the start. π
class MakeTransferViewModel(
private val transfersRepository: TransfersRepository
) : ViewModel() {
private val _uiState = MutableStateFlow<MakeTransferUiState>(...)
val uiState: StateFlow<MakeTransferUiState> = _uiState.asStateFlow()
private var makeTransferJob: Job? = null
fun tryTransfer() {
if (makeTransferJob != null) return
makeTransferJob = viewModelScope.launch {
try {
_uiState.update { it.copy(isLoading = true) }
val isTransferSuccessful = transfersRepository.makeTransfer(...)
_uiState.update {
it.copy(
isLoading = false,
transferResult = TransferResult(it.transferInfo, isTransferSuccessful)
)
}
} catch (ioe: IOException) {
_uiState.update {
it.copy(isLoading = false, error = ioe.message ?: "Error doing transfer")
}
} finally {
makeTransferJob = null
}
}
}
}