2017-03-02 28 views
9

Tôi chỉ mới bắt đầu học coroutines Kotlin và đã cố gắng để mô phỏng một thời gian dài API cuộc gọi với hiển thị kết quả trên giao diện người dùng:Làm thế nào để sử dụng coroutines Kotlin chờ đợi() trên chủ đề chính

class MainActivity : AppCompatActivity() { 
    fun log(msg: String) = println("[${Thread.currentThread().name}] $msg") 

    override 
    fun onCreate(savedInstanceState: Bundle?) { 
     super.onCreate(savedInstanceState) 
     this.setContentView(R.layout.activity_main) 
     val resultTV = findViewById(R.id.text) as TextView 

     val a = async(CommonPool) { 
      delay(1_000L) 
      6 
     } 

     val b = async(CommonPool) { 
      delay(1_000L) 
      7 
     } 

     launch(< NEED UI thread here >) { 
      val aVal = a.await() 
      val bVal = b.await() 
      resultTV.setText((aVal * bVal).toString()) 
     } 
    } 
} 

tôi không hiểu làm thế nào tôi có thể sử dụng phương pháp launch với ngữ cảnh main.

Thật không may, tôi không thể tìm thấy bất kỳ điều gì về việc cung cấp kết quả cho một số chủ đề cụ thể trên the official tutorial for coroutines.

+0

Xin lỗi, nơi mà bạn đã tìm thấy 'phương pháp launch'? –

+2

Có lẽ thư viện này sẽ giúp bạn https://github.com/metalabdesign/AsyncAwait –

+0

Tôi muốn thông qua thư viện, nhưng tôi chỉ lo lắng là có thể làm bằng cách sử dụng chỉ kotlinx.coroutines tiêu chuẩn. –

Trả lời

9

Sửa:

Xem thêm an official example in Kotlin repo

bạn cần phải thực hiện giao diện Continuation mà làm cho một callback lên Android UI thread và Coroutine context

ví dụ (Từ here)

private class AndroidContinuation<T>(val cont: Continuation<T>) : Continuation<T> by cont { 
    override fun resume(value: T) { 
     if (Looper.myLooper() == Looper.getMainLooper()) cont.resume(value) 
     else Handler(Looper.getMainLooper()).post { cont.resume(value) } 
    } 
    override fun resumeWithException(exception: Throwable) { 
     if (Looper.myLooper() == Looper.getMainLooper()) cont.resumeWithException(exception) 
     else Handler(Looper.getMainLooper()).post { cont.resumeWithException(exception) } 
    } 
} 

object Android : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor { 
    override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = 
     AndroidContinuation(continuation) 
} 

Sau đó thử:

launch(Android) { 
    val aVal = a.await() 
    val bVal = b.await() 
    resultTV.setText((aVal * bVal).toString()) 
} 

biết thêm:

https://medium.com/@macastiblancot/android-coroutines-getting-rid-of-runonuithread-and-callbacks-cleaner-thread-handling-and-more-234c0a9bd8eb#.r2buf5e6h

+0

Vui lòng tham khảo thư viện chính thức dành cho android coroutines -> https://github.com/gildor/kotlin-coroutines-android/blob/master/coroutines-android/README.md –

+0

Có phải từ JetBrains hoặc nhóm Android không? Ý bạn là gì? – pt2121

+2

Rất tiếc, đã dán liên kết sai. Sau đây là từ nhóm Kotlin để xử lý coroutines trong android https://github.com/Kotlin/kotlinx.coroutines/blob/master/ui/kotlinx-coroutines-android/src/main/kotlin/kotlinx/coroutines/experimental /android/HandlerContext.kt –

8

Bạn phải thay thế < NEED UI thread here > trong mã của bạn với UI bối cảnh từ kotlinx-coroutines-android mô-đun của dự án kotlinx.coroutines. Cách sử dụng của nó được giải thích trong Guide to UI programming with coroutines với một vài ví dụ.

0

Anko có một wrapper để làm điều đó rất simply-- see: https://github.com/Kotlin/anko/wiki/Anko-Coroutines

private fun doCallAsync() = async(UI) { 

    val user = bg { getUser() } 
    val name = user.await().name 
    val nameView = findViewById(R.id.name) as TextView 

    nameView.text = name; 

} 
1

Trước hết bao gồm thư viện đúng thiết kế dành cho Android

build.gradle

apply plugin: 'kotlin-android' 
apply plugin: 'kotlin-android-extensions' 

android{ 
... 
    dependencies{ 
     ... 
     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.19.3" 

    } 

    kotlin { 
    experimental { 
     coroutines "enable" 
    } 
    } 
} 

Sau đó, bạn được tự do sử dụng UI

suspend private fun getFilteredGList(enumList: List<EnumXXX>) = mList.filter { 
    ... 
} 

private fun filter() { 
    val enumList = listOf(EnumX1, EnumX2) 
    launch(UI){ 
     val filteredList = getFilteredList(enumList) 
     setMarkersOnMap(filteredList) 
    } 

} 
Các vấn đề liên quan