Android開發中的Kotlin Coroutine VS RxJava

前言

首先,我是個Kotlin的重度使用者。我用Kotlin寫事後臺應用,寫過前端,寫過近10個Android項目。前端

我我的以爲,Kotlin充滿了現代化的軟件開發所需的語言特點,在我用過的全部語言中(ES6,Python,Go,Java)是最舒服最天然的;JetBrain作了多年IDE,最懂開發者的尿性。若是你會Java,幾乎沒有學習成本。除了其餘優秀的語法外,我也格外喜歡Coroutine,下面就來吹一波。git

先吹一波

Coroutine,也叫協程,或者微線程(或者隨便你怎麼叫它);它是可暫停可恢復的比線程更小的任務單元。目前我所用到的支持協程序的語言有NodeJS,Go,Python;Java並不支持。從原理上看,它們的核心實現原理大都是OS Thread Pool + 狀態機,就是靠系統線程池來調度,靠狀態機來控制狀態。只不過有些是語言自然就支持的,好比Go;而Kotlin是用編譯技術來實現的。github

無論如何實現,它們通常有這樣2個好處:網絡

  1. 更低資源消耗和更好的調度性能
  2. 異步代碼變同步

至於第一點在Web應用上很實用,由於Web大可能是IO密集,它在低配置的機器上能夠帶來更高的併發,資源消耗還少。可是在Andorid上然並卵,就算是多線程下載的場景,通常併發任務也就5個左右,根本體現不出它的做用。多線程

第二點在Android上就很實用了,咱們常常會遇到先執行一段耗時操做,在執行一段後續邏輯的場景。否則Andorid也不會搞出AsyncTask,IntentService,HandlerThread了。它能夠徹底消除咱們的callback。併發

場景

先看一個真實的發佈動態場景。動態中包含文字,用戶拍攝或選擇的9張圖片。整個動態的發佈流程是這樣:異步

  1. 先異步對9張圖片進行壓縮
  2. 而後異步將9張圖片上傳到Server,拿到9個圖片Id
  3. 將文字和圖片Id一塊上傳

第1步,第2步和第3步自己都是須要異步,但1,2,3步之間又是同步順序執行的關係。post

Java中能夠用FutureTask實現。性能

用RxJava來作大概是大量的Callback流配合map操做符來完成,代碼雖然比FetureTask好不少,可是並不美觀。學習

用Kotlin Coroutine來作就是:

GlobalScope.launch {
    // 其餘參數
    val params = hashMapOf(
            "content" to content,
            "longitude" to longitude,
            "latitude" to latitude,
            "title" to title
    )
    
    //1. 構建壓縮圖片的task
    val compressedTasks = paths.map { compressImage(it) } // paths是用戶的圖片地址集合
    //2. 構建上傳圖片的task,上傳任務就是http請求
    val uploadTasks = compressedTasks.map { uploadImage(it.await()) } //壓縮任務併發執行
    //3. 執行上傳圖片task拿到結果
    val imageIds = uploadTasks.map { it.await()!!.data.id } // 上傳圖片任務併發執行
    params["images"] = imageIds.toJson()

    val result = "$BASEURL/weibo/create".http(this)
            .headers(...)
            .params(params)
            .post<HttpResult<Dynamic>>().await()
            
    // 更新LiveData 
    weiboCreateData.postValue(result)
}
複製代碼

幾個構建task的代碼在這裏:

/** * 構建壓縮任務 */
fun compressImage(path: String): Deferred<File>{
    val deferred = CompletableDeferred<File>()
    // 這裏是使用Luban庫來壓縮圖片,具體邏輯能夠忽略
    deferred.complete(Luban.with(App.context)
            .load(path)
            .ignoreBy(100)
            .get()[0])
    return deferred
}

/** * 構建上傳圖片的任務 */
fun uploadImage(file: File): Deferred<HttpResult<List<UploadData>>?> {
    return "$BASEURL/weibo/upload".http(this)
            .headers(createCommonHeaders(null))
            .params("file" to file)
            .post<HttpResult<List<UploadData>>>()
}
複製代碼

能夠看到這種複雜邏輯下,所有代碼也就30行左右,而且沒有一個Callback,是否是比RxJava好。

上面的網絡請求是來自於個人一個庫:github.com/li-xiaojun/…

異步邏輯以後通知UI,我建議用LiveData,省去不少界面銷燬的判斷,並且監聽能夠自動解除註冊,RxJava還要手動dispose。

若是你就想在UI中執行一段異步邏輯而後回到UI線程更新UI,那能夠用anko庫的封裝。

最後

其實,我並不用RxJava,從看到大量的Callback時就放棄了。

我對RxJava並無深刻了解,對於上面的場景,若是RxJava能作的更好,煩請指出。

相關文章
相關標籤/搜索