2017-03-16 1 views
5

Android UI 스레드의 컨텍스트에서 공동 루틴을 사용하려고합니다. Coroutines Guide UI에 설명 된대로 contextJob을 구현했습니다. 백그라운드 작업은 GUI에서 쳐다 보면서 클릭 할 때마다 다시 시작 (현재 실행중인 작업을 중지하고 다시 시작)하고 싶습니다.Job 인스턴스를 다시 사용할 수 있습니까?

그러나 한때 심지어 아이 작업을 생성 다시 사용할 수 없습니다 취소 작업 :

val job = Job(contextJob) 

하고 - 재 할당 할 수 있기 때문에 도움이되지 않는 취소.

Job 인스턴스를 다시 사용할 수 있습니까?

답변

4

Job은 디자인별로 매우 간단한 라이프 사이클을 갖고 있습니다. "완료 됨"상태는 최종이며, 안드로이드 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을 시작합니다. 그러나 의 각 호출은 withContext 블록을 사용하여 자체 Job으로 래핑되므로 상위 작업과 별도로 취소 할 수 있습니다.

이 코드는 취소 할 수없는 동작이나 취소하는 데만 시간이 걸립니다. 조치는 취소 될 때 해당 자원을 정리해야 할 수도 있으며,이 코드는 행위자를 사용하므로 다음 조치가 시작되기 전에 이전 조치의 정리가 완료되도록합니다.

관련 문제