Jobは、設計により非常に単純なライフサイクルを有する。その「完了」状態はの最終であり、AndroidのActivity
の「破棄」状態に非常に似ています。したがって、親のJob
は、ガイドで説明されているように、Activity
に関連付けられることをお勧めします。アクティビティが破棄された場合にのみ、親ジョブをキャンセルする必要があります。破壊されたアクティビティは再利用できないため、ジョブを再利用する必要はありません。
各クリックで作業を開始するための推奨される方法は、不必要な並行性を避けるためにアクターを使用することです。このガイドでは、クリックごとに開始する方法を示していますが、現在実行中の操作をキャンセルする方法は示されていません。俳優は常にアクティブで
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
}
}
は、その親ジョブまで(アクティビティに添付:
あなたは他のすべてとは別に、コード解約のブロックを作るためにwithContext
との組み合わせでJob
の新鮮なインスタンスが必要になります)がキャンセルされます。俳優はクリックを待ち、クリックごとにaction
を開始します。ただし、action
の各呼び出しは、withContext
ブロックを使用して自身のJob
にラップされるため、親ジョブとは別にキャンセルできます。
このコードは、取り消しできない、または取り消すまでに時間がかかることに注意してください。アクションは、リソースが取り消されたときにそのリソースをクリーンアップする必要があり、このコードはアクターを使用するため、前のアクションのクリーンアップが次のアクションの開始前に完了するようにします。