Home > Blockchain >  How to handle Coroutines jobs
How to handle Coroutines jobs

Time:12-21

I have a viewmodel that has a method. there are 4 conditions base on 4 Buttons that each condition can run separately by viewModelScope in this method. Now I want to stop and restart each viewModelScope separately but I don't know how. When I cancel the viewModelScope by job1.cancel(), I can't start it again.

This is my code that I want to handle that:

fun calculateDistance(tripId: Int) = viewModelScope.launch {
    var currentCost: Double = 6500.0
    var partCost: Double = 0.0
    while (isActive) {
        localRepository.getUnCalculatedLocation(tripId).collect { result ->
            if (result.data!!.isNotEmpty()) {
                result.data.forEach {

                    var passId = 0
                    val distance = Calculates.distance(
                        lat1 = if (it.latitude1 != 0.0) it.latitude1 else it.latitudeNet1,
                        lat2 = if (it.latitude2 != 0.0) it.latitude2 else it.latitudeNet2,
                        long1 = if (it.longitude1 != 0.0) it.longitude1 else it.longitudeNet1,
                        long2 = if (it.longitude2 != 0.0) it.longitude2 else it.longitudeNet2
                    )
                    localRepository.getPassId(it.tripId!!.toInt()).collect { id ->
                        if (id.data != null) {
                            passId = id.data
                        }
                    }
                    var passDistance = PassengerDistance(passId, distance)
                    _passDistance.postValue(passDistance)
                    localRepository.updateLocation(distance, it.id)

                   
                    var uniqueId = ""
                    localRepository.getUniqueId(it.tripId).collect { uid ->
                        uniqueId = uid.data!!
                    }
                    when (passId) {
                        1 -> {

                            job1.launch {
                                _tripTime1.postValue(_tripTime1.value?.plus(2000))
                                if (distance == 0.0) {
                                    if (secondCost1 < 10) secondCost1  = 2
                                    else {
                                        val expression: Expression =
                                            Expression(_formula.value?.stoppingFormula)
                                        val resultCost: EvaluationValue =
                                            expression.with("T", secondCost1).evaluate()
                                        currentCost =
                                            if (_costPass1.value == null) constCost.toDouble() else _costPass1.value!!

                                        partCost = resultCost.numberValue.toDouble()

                                        _costPass1.postValue(resultCost.numberValue.toDouble()   currentCost)
                                        secondCost1 = 0
                                    }

                                } else {
                                    val expression: Expression =
                                        Expression(_formula.value?.movingFormula)
                                    val resultCost: EvaluationValue =
                                        expression.with("D", distance * 1000).evaluate()
                                    val resultTest = (2109 / 200) * distance
                                    currentCost =
                                        if (_costPass1.value == null) constCost.toDouble() else _costPass1.value!!
                                    partCost = resultCost.numberValue.toDouble()
                                    var two = partCost * 2
                                    Log.d(
                                        "DISTANCE",
                                        "actual cost is $partCost , Test: $resultTest"
                                    )
                                    _costPass1.postValue((resultCost.numberValue.toDouble() * 2)   currentCost)

                                    _tripDistance1.postValue(
                                        _tripDistance1.value?.plus(
                                            distance
                                        )
                                    )

                                }


                                localRepository.updateCurrentCost(partCost, it.id!!)


                                val saveLocation = TripDetails(
                                    id = it.id,
                                    latitude1 = it.latitude1,
                                    latitude2 = it.latitude2,
                                    longitude1 = it.longitude1,
                                    longitude2 = it.longitude2,
                                    accuracy1 = it.accuracy1,
                                    accuracy2 = it.accuracy2,
                                    latitudeNet1 = it.latitudeNet1,
                                    latitudeNet2 = it.latitudeNet2,
                                    longitudeNet1 = it.longitudeNet1,
                                    longitudeNet2 = it.longitudeNet2,
                                    accuracy1Net = it.accuracy1Net,
                                    accuracy2Net = it.accuracy2Net,
                                    tripId = it.tripId,
                                    distance = distance,
                                    isCalculated = true,
                                    isEnded = it.isEnded,
                                    date = it.date,
                                    cost = partCost,
                                    uniqueId = uniqueId,
                                    isMonitor = _isMonitor.value!!,
                                    driverId = _driver.value?.data?.driverId!!
                                )
                                try {
                                    repository.saveLocation(saveLocation).let { result ->
                                        if (result.isSuccessful) {
                                            Log.d("TAG", result.body()?.result.toString())
                                        } else {
                                            Log.d("TAG", result.body()?.message!!)
                                        }
                                    }
                                } catch (e: Exception) {
                                    Log.d("Error", e.message.toString())
                                }
                            }

                        }


                        2 -> {
                            job2.launch {
                                _tripTime2.postValue(_tripTime2.value?.plus(2000))
                                if (distance == 0.0) {
                                    if (secondCost2 < 10) secondCost2  = 2
                                    else {
                                        val expression: Expression =
                                            Expression(_formula.value?.stoppingFormula)
                                        val resultCost: EvaluationValue =
                                            expression.with("T", secondCost2).evaluate()
                                        currentCost =
                                            if (_costPass2.value == null) constCost.toDouble() else _costPass2.value!!
                                        _costPass2.postValue(resultCost.numberValue.toDouble()   currentCost)
                                        partCost = resultCost.numberValue.toDouble()
                                        secondCost2 = 0
                                    }

                                } else {
                                    val expression: Expression =
                                        Expression(_formula.value?.movingFormula)
                                    val resultCost: EvaluationValue =
                                        expression.with("D", distance * 1000).evaluate()
                                    currentCost =
                                        if (_costPass2.value == null) constCost.toDouble() else _costPass2.value!!
                                    _costPass2.postValue(resultCost.numberValue.toDouble()   currentCost)
                                    partCost = resultCost.numberValue.toDouble()
                                    _tripDistance2.postValue(_tripDistance2.value?.plus(distance))

                                }

                                val saveLocation = TripDetails(
                                    id = it.id,
                                    latitude1 = it.latitude1,
                                    latitude2 = it.latitude2,
                                    longitude1 = it.longitude1,
                                    longitude2 = it.longitude2,
                                    accuracy1 = it.accuracy1,
                                    accuracy2 = it.accuracy2,
                                    latitudeNet1 = it.latitudeNet1,
                                    latitudeNet2 = it.latitudeNet2,
                                    longitudeNet1 = it.longitudeNet1,
                                    longitudeNet2 = it.longitudeNet2,
                                    accuracy1Net = it.accuracy1Net,
                                    accuracy2Net = it.accuracy2Net,
                                    tripId = it.tripId,
                                    distance = distance,
                                    isCalculated = true,
                                    isEnded = it.isEnded,
                                    date = it.date,
                                    cost = partCost,
                                    uniqueId = uniqueId,
                                    isMonitor = _isMonitor.value!!,
                                    driverId = _driver.value?.data?.driverId!!
                                )
                                try {
                                    repository.saveLocation(saveLocation).let { result ->
                                        if (result.isSuccessful) {
                                            Log.d("TAG", result.body()?.result.toString())
                                        } else {
                                            Log.d("TAG", result.body()?.message!!)
                                        }
                                    }
                                } catch (e: Exception) {
                                    Log.d("Error", e.message.toString())
                                }
                            }

                        }

                        3 -> {
                            job3.launch {
                                _tripTime3.postValue(_tripTime3.value?.plus(2000))
                                if (distance == 0.0) {
                                    if (secondCost3 < 10) secondCost3  = 2
                                    else {
                                        val expression: Expression =
                                            Expression(_formula.value?.stoppingFormula)
                                        val resultCost: EvaluationValue =
                                            expression.with("T", secondCost3).evaluate()
                                        currentCost =
                                            if (_costPass3.value == null) constCost.toDouble() else _costPass3.value!!
                                        _costPass3.postValue(resultCost.numberValue.toDouble()   currentCost)
                                        partCost = resultCost.numberValue.toDouble()
                                        secondCost3 = 0
                                    }

                                } else {
                                    val expression: Expression =
                                        Expression(_formula.value?.movingFormula)
                                    val resultCost: EvaluationValue =
                                        expression.with("D", distance * 1000).evaluate()
                                    currentCost =
                                        if (_costPass3.value == null) constCost.toDouble() else _costPass3.value!!
                                    _costPass3.postValue(resultCost.numberValue.toDouble()   currentCost)
                                    partCost = resultCost.numberValue.toDouble()
                                    _tripDistance3.postValue(_tripDistance3.value?.plus(distance))

                                }

                                val saveLocation = TripDetails(
                                    id = it.id,
                                    latitude1 = it.latitude1,
                                    latitude2 = it.latitude2,
                                    longitude1 = it.longitude1,
                                    longitude2 = it.longitude2,
                                    accuracy1 = it.accuracy1,
                                    accuracy2 = it.accuracy2,
                                    latitudeNet1 = it.latitudeNet1,
                                    latitudeNet2 = it.latitudeNet2,
                                    longitudeNet1 = it.longitudeNet1,
                                    longitudeNet2 = it.longitudeNet2,
                                    accuracy1Net = it.accuracy1Net,
                                    accuracy2Net = it.accuracy2Net,
                                    tripId = it.tripId,
                                    distance = distance,
                                    isCalculated = true,
                                    isEnded = it.isEnded,
                                    date = it.date,
                                    cost = partCost,
                                    uniqueId = uniqueId,
                                    isMonitor = _isMonitor.value!!,
                                    driverId = _driver.value?.data?.driverId!!
                                )
                                try {
                                    repository.saveLocation(saveLocation).let { result ->
                                        if (result.isSuccessful) {
                                            Log.d("TAG", result.body()?.result.toString())
                                        } else {
                                            Log.d("TAG", result.body()?.message!!)
                                        }
                                    }
                                } catch (e: Exception) {
                                    Log.d("Error", e.message.toString())
                                }
                            }

                        }

                        4 -> {
                            job4.launch {
                                _tripTime4.postValue(_tripTime4.value?.plus(2000))
                                if (distance == 0.0) {
                                    if (secondCost4 < 10) secondCost4  = 2
                                    else {
                                        val expression: Expression =
                                            Expression(_formula.value?.stoppingFormula)
                                        val resultCost: EvaluationValue =
                                            expression.with("T", secondCost4).evaluate()
                                        currentCost =
                                            if (_costPass4.value == null) constCost.toDouble() else _costPass4.value!!
                                        _costPass4.postValue(resultCost.numberValue.toDouble()   currentCost)
                                        partCost = resultCost.numberValue.toDouble()
                                        secondCost4 = 0
                                    }

                                } else {
                                    val expression: Expression =
                                        Expression(_formula.value?.movingFormula)
                                    val resultCost: EvaluationValue =
                                        expression.with("D", distance * 1000).evaluate()
                                    currentCost =
                                        if (_costPass4.value == null) constCost.toDouble() else _costPass4.value!!
                                    _costPass4.postValue(resultCost.numberValue.toDouble()   currentCost)

                                    partCost = resultCost.numberValue.toDouble()
                                    _tripDistance4.postValue(_tripDistance4.value?.plus(distance))

                                }

                                val saveLocation = TripDetails(
                                    id = it.id,
                                    latitude1 = it.latitude1,
                                    latitude2 = it.latitude2,
                                    longitude1 = it.longitude1,
                                    longitude2 = it.longitude2,
                                    accuracy1 = it.accuracy1,
                                    accuracy2 = it.accuracy2,
                                    latitudeNet1 = it.latitudeNet1,
                                    latitudeNet2 = it.latitudeNet2,
                                    longitudeNet1 = it.longitudeNet1,
                                    longitudeNet2 = it.longitudeNet2,
                                    accuracy1Net = it.accuracy1Net,
                                    accuracy2Net = it.accuracy2Net,
                                    tripId = it.tripId,
                                    distance = distance,
                                    isCalculated = true,
                                    isEnded = it.isEnded,
                                    date = it.date,
                                    cost = partCost,
                                    uniqueId = uniqueId,
                                    isMonitor = _isMonitor.value!!,
                                    driverId = _driver.value?.data?.driverId!!
                                )
                                try {
                                    repository.saveLocation(saveLocation).let { result ->
                                        if (result.isSuccessful) {
                                            Log.d("TAG", result.body()?.result.toString())
                                        } else {
                                            Log.d("TAG", result.body()?.message!!)
                                        }
                                    }
                                } catch (e: Exception) {
                                    Log.d("Error", e.message.toString())
                                }
                            }

                        }
                    }

                }
            }

        }
        delay(2000)
    }

}

Here there is a when statement that has 4 conditions. There are 4 Buttons for each conditions. The a

CodePudding user response:

The code is complicated. It's hard to understand the workflow.

If you want to run a new job for the phase and cancel it for some reason. You have to create a new Job for each phase.

1 -> {
    job1 = viewModelScope.launch {
...
4 -> {
    job4 = viewModelScope.launch {

UPDATE based on comments:

In your code you define variables:

val job1 = viewModelScope
val job2 = viewModelScope
...

This is not a job definition, this is just a new variables with reference to the viewModelScope.

So when you call job1.cancel() it equals to call viewModelScope.cancel(). The result the viewModelScope is canceled and no coroutine can be started.

To change it you can refactor your code to use a job:

@field:Volatile
var job1: Job? = null
@field:Volatile
var job2: Job? = null
...

Create a new job for the each phase in fun calculateDistance(tripId: Int):

1 -> {
    job1 = viewModelScope.launch {
2 -> {
    job2 = viewModelScope.launch {

To cancel a job in the other code you have to use the following code:

job1?.cancel()
  • Related