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()
