0

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

2
  • If you canceled job, just create a new job, it is by design. Commented Dec 20, 2022 at 8:33
  • @Yurii How can I create a Job? With job.launch ? if I cancel a specific job, all viewModelScope's jobs cancel? Commented Dec 20, 2022 at 10:09

1 Answer 1

1

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()
Sign up to request clarification or add additional context in comments.

8 Comments

I do that. I create a new job for each phrase. So I can stop each Job successfully but I can't re-run them. Even I use a method and in that method launch the job, but in that way it doesn't work too
The each call job1 = viewModelScope.launch have to create a new job and start it. You don't cancel viewModelScope don't it?
Let me tell you what did I do exactly. I initialize global variables for Coroutines job: val job1 = viewModelScope . Then in a method I use job1.launche{ }. By a Boolean variable I check that should I cancel the job or not. If yes, I call job1.cancel. after that other viewModelScope will not run anymore
So finally val job1 = viewModelScope it is not a job this is the reference to viewModelScope. And when you cancel job1..4 the viewModelScope canceled. After no one coroutine can be started in viewModelScope.
Ok, So what should I do? Please write the correct code. Thanks
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.