是繼續Rxjava還是該試試Kotlin的協程,你真的知道嘛?

0.前言

協程以前一直是Kotlin作爲實驗性的一個庫,前些日子發現1.3版本的kotlin relese了協程,所以就找時間研究了一下,本來早就想寫這篇文章了,但是因爲離職換工作的原因,遲遲未能動筆,這兩天終於算搞完了,記錄一下我對協程的一些理解。

1.什麼是協程

1.1協程定義

我第一次接觸協程是在python的教程裏,這裏拿來用來解釋一下:子程序,或者稱爲函數,在所有語言中都是層級調用,比如A調用B,B在執行過程中又調用了C,C執行完畢返回,B執行完畢返回,最後是A執行完畢。所以子程序調用是通過棧實現的,一個線程就是執行一個子程序。子程序調用總是一個入口,一次返回,調用順序是明確的。而協程的調用和子程序不同。協程看上去也是子程序,但執行過程中,在子程序內部可中斷,然後轉而執行別的子程序,在適當的時候再返回來接着執行。注意,在一個子程序中中斷,去執行其他子程序,不是函數調用,有點類似CPU的中斷。

1.2協程和線程的關係

協程和線程,都能用來實現異步調用,但是這兩者之間是有本質區別的

(1)協程是編譯器級別的,線程是系統級別的。協程的切換是由程序來控制的,線程的切換是由操作系統來控制的。

(2)協程是協作式的,線程是搶佔式的。協程是由程序來控制什麼時候進行切換的,而線程是有操作系統來決定線程之間的切換的。

(3)一個線程可以包含多個協程。

(4)Java中,多線程可以充分利用多核cpu,協程是在一個線程中執行。

(5)協程適合io密集型的程序,多線程適合計算密集型的程序(適用於多核cpu的情況)。當你的程序大部分是文件讀寫操作或者網絡請求操作的時候,這時你應該首選協程而不是多線程,首先這些操作大部分不是利用cpu進行計算而是等待數據的讀寫,其次因爲協程執行效率較高,子程序切換不是線程切換,是由程序自身控制,因此,沒有線程切換的開銷,和多線程比,線程數量越多,協程的性能優勢就越明顯。

(6)使用協程可以順序調用異步代碼,避免回調地獄。

2.簡單用法

這裏我打算模仿一個網絡請求,點擊button發送網絡請求,顯示一個progressbar打轉,返回結果後一個textview顯示結果並隱藏progressbar

先看一下佈局文件

     <?xml version="1.0" encoding="utf-8"?>

<FrameLayout

        xmlns:android="http://schemas.android.com/apk/res/android"

        xmlns:tools="http://schemas.android.com/tools"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        tools:context=".MainActivity">

  <TextView

        android:id="@+id/timeTV"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"/>

  <Button

        android:id="@+id/sendBT"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="SEND"

        android:layout_gravity="center"/>

  <ProgressBar

        android:layout_gravity="center"

        android:visibility="gone"

        android:id="@+id/loadingPB"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"/>

</FrameLayout>


一個Button,一個TextView,一個ProgressBar

class MainActivity : AppCompatActivity(){

override fun onCreate(savedInstanceState: Bundle?){

                    super.onCreate(savedInstanceState)

                    setContentView(R.layout.activity_main)

                    sendBT.setOnClickListener{

                              coroutineSend()

                    }

}

private fun coroutineSend(){

                val uiScope = CoroutineScope(Dispatchers.Main)

                uiScope.launch{

                         loadingPB.visibility = View.VISIBLE

                         val deffer = async(Dispatchers.Default){

                                   getCoroutineResult()

                     }

                     val coroutineResult = deffer.await()

                     timeTV.text = "get $coroutineResult"

                     loadingPB.visibility = View.GONE

             }

}

private suspend fun get CoroutineResult():String{

           delay(9000L)

            return "coroutine result"

             }

}

首先創建了一個CoroutineScope,所有協程都運行在CoroutineScope中,創建CoroutineScop中傳入參數Dispatchers.Main,這是一個協程調度器,它確定了相應的協程在執行時使用一個或多個線程。協程調度器可以將協程的執行侷限在指定的線程中,調度它運行在線程池中或讓它不受限的運行。 調用launch,就啓動了一個協程,launch方法會返回一個job,調用cancel方法可以取消這個協程的進行。可以看到在協程裏我們先展示出loadingPB,然後調用async又啓動一個協程,同時使用Dispatchers.Default這個協程調度器,它將使協程在執行時使用一個DefaultDispatcher-worker-1線程,這裏爲什麼使用async而沒有使用launch,是因爲async會返回一個Deferred對象,調用其await方法可以阻塞執行流等到協程執行完畢返回結果,這樣可以得到一個返回值,在這個async創建的協程裏使用了使用了suspend方法

private suspend fun getCoroutineResult():String{

              delay(9000L)

              return"coroutine result"

       }

先休眠9秒鐘,然後返回一個字符串,注意這裏這個delay也是suspend方法,一個suspend方法只能在協程或者suspend方法裏調用。關於協程還有一些其他的創建和使用方法,有興趣的可以去看看官方教程。

3.Rxjava VS 協程

協程相對RxJava有什麼優點呢?

(1)RxJava堆棧可讀性查,一旦出現問題,堆棧信息爆炸,難以定位問題,而協程就可以避免這個問題

(2)協程用同步的方式寫異步的代碼,美好了生活,方便代碼閱讀。

(3)協程學習曲線比較平坦,相對於RxJava,協程對初學者更易於學習。

爲了讓學習變得輕鬆、高效,今天給大家免費分享一套阿里p7架構師傳授的一套教學資源。幫助大家在成爲架構師的道路上披荊斬棘。

詳細講解了(高級UI、性能優化、熱修復、熱更新、NDK、Kotlin進階、混合式開發(ReactNative+Weex))等成爲架構師必備的內容!

關注我私信回覆【學習】或加入Android架構交流羣:513088520免費獲取以上資料!!!

4.最後

這年頭用Kotlin來開發android應用確實越來越爽快了,一些新的特性也逐漸加入到Kotlin中,值得更加學習,當然還有Flutter,以後會陸續寫幾個關於Flutter的文章,畢竟release了,我對它是十分看好的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章