2017-03-16 53 views
5

Android UI dizisi bağlamında birlikte çalışma rutinlerini araştırıyorum. Coroutines Guide UI'da açıklandığı gibi contextJob uygulandım. Arkaplan çalışması GUI'den izlenir ve her tıklamayla yeniden başlatmak istiyorum (şu anda çalışmakta olanı durdurun ve tekrar başlatın).Bir İş örneğini yeniden kullanmanın bir yolu var mı?

Ama bir kez bu kadar bile bir çocuk işi yaratarak yeniden kullanılamaz iptal bir iş:

val job = Job(contextJob) 

ve-yeniden gerektiğinden yardımcı olmuyor iptal.

Bir İş örneğini yeniden kullanmanın bir yolu var mı?

cevap

4

A Job, tasarım gereği çok basit bir kullanım ömrüne sahiptir. "Tamamlandı" durumu, Android Activity'un "Yokedildi" durumuna çok benzeyen final. Dolayısıyla, Job numaralı bir ebeveynin kılavuzda açıklandığı gibi bir Activity ile ilişkilendirilmesi en iyisidir. Bir aktiviteyi sadece ve eğer faaliyet imha edilirse iptal etmelisiniz. Yok edilen bir etkinlik yeniden kullanılamayacağından, işini yeniden kullanma gereksinimine asla girmezsiniz.

Her tıklamada çalışmaya başlamak için önerilen yaklaşım, gereksiz eşzamanlılıklardan kaçınmanıza yardımcı oldukları için, aktörler kullanmaktır. Kılavuz, her tıklamanın nasıl başlatılacağını gösterir, ancak şu anda çalışan bir eylemin nasıl iptal edileceğini göstermez. Bir aktör daima aktiftir

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 
    } 
} 

üst işinde kadar (bir etkinliğe ekli:

Sen her şey ayrı kod iptal bloğunu yapmak withContext ile birlikte Job taze örneğini gerekecektir) iptal edildi. Bir oyuncu tıklamaları bekler ve her tıklamada bir action başlatır. Bununla birlikte, her bir action çağrısı,bloğunu kullanarak kendi Job koduna sarılır, böylece ana işinden ayrı olarak iptal edilebilir.

Not: Bu kod, iptal edilemeyen veya yalnızca iptal etmek için biraz zaman ayırdığınız eylemler için işe yarar. Bir işlem iptal edildiğinde kaynaklarını temizlemeye ihtiyaç duyabilir ve bu kod bir aktör kullandığı için, önceki işlemin temizlenmesinin bir sonraki başlatılmadan önce bitmesini sağlar.