A Job ma bardzo prosty cykl życia według projektu. Jego stan "Completed" to final, bardzo podobny do stanu "Zniszczone" systemu Android Activity
. Tak więc rodzic Job
najlepiej jest skojarzyć z Activity
, jak wyjaśniono w przewodniku. Powinieneś anulować zadanie nadrzędne tylko wtedy, gdy działanie zostanie zniszczone. Ponieważ zniszczonej działalności nie można ponownie wykorzystać, nigdy nie napotkasz potrzeby ponownego wykorzystania jej pracy.
Zalecanym podejściem do rozpoczęcia pracy przy każdym kliknięciu jest użycie aktorów, ponieważ pomagają uniknąć niepotrzebnej współbieżności. Przewodnik pokazuje, jak je uruchomić po każdym kliknięciu, ale nie pokazuje, jak anulować aktualnie działającą akcję.
Będziesz potrzebował świeżego wystąpienie Job
w połączeniu z withContext
aby blok kodu odwoływalny niezależnie od wszystkiego innego:
fun View.onClick(action: suspend() -> Unit) {
var currentJob: Job? = null // to keep a reference to the currently running job
// launch one actor as a parent of the context job
// actor prevent concurrent execution of multiple actions
val eventActor = actor<Unit>(contextJob + UI, capacity = Channel.CONFLATED) {
for (event in channel) {
currentJob = Job(contextJob) // create a new job for this action
try {
// run an action within its own job
withContext(currentJob!!) { action() }
} catch (e: CancellationException) {
// we expect it to be cancelled and just need to continue
}
}
}
// install a listener to send message to this actor
setOnClickListener {
currentJob?.cancel() // cancel whatever job we were doing now (if any)
eventActor.offer(Unit) // signal to start next action when possible
}
}
Aktor jest zawsze aktywna aż do jej pracy dominującej (dołączonym do aktywności) jest odwołany. Aktor czeka na kliknięcia i uruchamia po każdym kliknięciu action
. Jednak każde wywołanie obiektu action
jest pakowane do własnego bloku przy użyciu bloku , dzięki czemu można je anulować niezależnie od zadania nadrzędnego.
Pamiętaj, że kod ten z powodzeniem działa w przypadku działań, których nie można anulować lub których anulowanie zajmuje trochę czasu. Działanie może wymagać wyczyszczenia zasobów po anulowaniu, a ponieważ ten kod używa aktora, zapewnia to, że czyszczenie poprzedniej czynności zostało zakończone przed uruchomieniem następnej.