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