Ich habe eine Berechnungsfunktion. Ich möchte diese Berechnung auch abbrechen, falls der Benutzer ändert, und starten Sie erneut, sobald der Benutzer auf eine Schaltfläche klickt. Im Inside ProductState delegiere ich diese Berechnung an einen Nicht-Main-Dispatcher, um die Benutzeroberfläche reaktionsschnell zu halten. Ich sammle auch die aus dieser Sequenz emittierten Elemente und aktualisiere die Fortschritte auf jedem empfangenen Element. < /P>
Code: Select all
val totalSize = 255 // for sake of this example
var input by rememberSaveable(stateSaver = TextFieldValue.Saver) {
mutableStateOf(TextFieldValue("Test Input"))
}
var doCalculation by rememberSaveable(input) {
mutableStateOf(false)
}
val resultState by produceState(
State.Null as State,
input,
doCalculation,
) {
value = DealingState.Null
if (!doCalculation) {
value = DealingState.Null
return@produceState
}
value = DealingState.Loading(
progress = 0,
required = totalSize,
)
launch(Dispatchers.Default) {
runCatching {
val resultList = mutableListOf()
calculateItems(input).forEach {
resultList.add(it)
value = State.Loading(
progress = resultList.size,
required = totalSize,
)
}
value = State.Success(resultList)
}.getOrElse {
value = State.Failure(it)
}
}
}
Ich habe die folgenden Dinge ausprobiert:
Definieren Sie einen Coroutine -Scope spezifisch für diese Routine und rufen Sie Scope () , wenn ein neuer Staat erzeugt wird.
Code: Select all
val scope = CoroutineScope(Dispatchers.Default)
val resultState by produceState(...) {
scope.cancel()
....
scope.launch(Dispatchers.Default) {...}
}
< /code>
Speichern Sie den Job beim Start < /code> und stornieren Sie den Job oder die Kinder < /li>
< /ul>
var job: Job? = null
val resultState by produceState(...) {
job?.cancel() // and job?.cancelChildren()
....
job = launch(Dispatchers.Default) {...}
}