首先祝大家端午節快樂,吃粽子了沒?哈哈,我今天一直在思考一個問題:端午節是為了紀念屈原老先生投江而在民間流傳下來的節日,這本是何等悲壯的一件事,為何時至今日,變成了一個好像很喜慶的日子,屈原老先生估計心想:老子TM只是感動了自己嗎?
言歸正傳,雖然是端午佳節,但是我等屌絲,藥不能停,世界一直在變化,要學會擁抱變化,今天想和大家分享的是協程,鄙人才識淺薄,還望諸公海涵,
首先想說的是為什么會有協程的出現?我們來看一下官方給我們的描述:
協程通過將復雜性放入庫來簡化異步編程,程式的邏輯可以在協程中順序地表達,而底層庫會為我們解決其異步性,該庫可以將用戶代碼的相關部分包裝為回呼、訂閱相關事件、在不同執行緒(甚至不同機器)上調度執行,而代碼則保持如同順序執行一樣簡單,
看懂了沒?我是沒太明白,哈哈,簡單的說,協程就是谷歌為了方便異步操作而設計的一套標準流程,為什么要有標準流程,Android開發老油條應該都知道,這么多年來,Android開發的發展史就是一部混亂的歷史,從網路請求到資料庫再到專案架構,各種技術第三方層出不窮,不同的人又有自己不同的想法,導致專案發展到最后也是處于一個混亂的狀態,
谷歌應該也開始意識到這個問題,開始推出了Jetpack,我認為協程和Jetpack有異曲同工之妙,
那么我們該如何使用協程呢?
首先我們需要添加依賴:
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:***"
后面三顆星不要直接抄,那是kotlin版本號,我在家也看不了那個基友網站(Github),不知道最新版本是多少了,
依賴添加好了我們來小試牛刀:
我們來看一段代碼:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.e("lzy", "主執行緒id:${mainLooper.thread.id}")
test()
Log.e("lzy", "協程執行結束")
}
private fun test() = runBlocking {
repeat(8) {
Log.e("lzy", "$it 執行緒id${Thread.currentThread().id}")
delay(1000)
}
}
}
運行一下我們的程式:
2021-06-13 04:51:46.447 5774-5774/com.example.b E/lzy: 主執行緒id:2
2021-06-13 04:51:46.453 5774-5774/com.example.b E/lzy: 0 執行緒id2
2021-06-13 04:51:47.456 5774-5774/com.example.b E/lzy: 1 執行緒id2
2021-06-13 04:51:48.459 5774-5774/com.example.b E/lzy: 2 執行緒id2
2021-06-13 04:51:49.461 5774-5774/com.example.b E/lzy: 3 執行緒id2
2021-06-13 04:51:50.462 5774-5774/com.example.b E/lzy: 4 執行緒id2
2021-06-13 04:51:51.465 5774-5774/com.example.b E/lzy: 5 執行緒id2
2021-06-13 04:51:52.469 5774-5774/com.example.b E/lzy: 6 執行緒id2
2021-06-13 04:51:53.471 5774-5774/com.example.b E/lzy: 7 執行緒id2
2021-06-13 04:51:54.472 5774-5774/com.example.b E/lzy: 協程執行結束
可見,runBlocking啟動的協程會阻斷當前執行緒,這種場景顯然并不是我們想要的那樣,
探索繼續,我們再來看一段代碼:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val job = GlobalScope.launch {
delay(6000)
Log.e("lzy", "協程執行結束")
}
Log.e("lzy", "主執行緒執行結束")
}
}
運行一下程式:
2021-06-13 04:55:31.597 5957-5957/com.example.b E/lzy: 主執行緒執行結束
2021-06-13 04:55:37.602 5957-5986/com.example.b E/lzy: 協程執行結束
這兩個日志間隔時間為6s,GlobalScope.launch啟動的協程并不會阻塞執行緒,
再介紹一個關鍵字:suspend,俗稱掛起函式,
我們來看一段代碼:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
GlobalScope.launch {
val token = getToken()
val userInfo = getUserInfo()
Log.e("lzy", "hello")
}
Log.e("lzy", "hi")
}
suspend fun getUserInfo() {
delay(3000)
}
suspend fun getToken() {
delay(3000)
}
}
運行結果:
2021-06-13 05:04:33.379 6205-6205/com.example.b E/lzy: hi
2021-06-13 05:04:39.392 6205-6234/com.example.b E/lzy: hello
這中間間隔了6s,suspend函式掛起后,協程體內代碼不會繼續往下執行,且不會阻塞主執行緒,
這樣看來,getToken()方法執行完了之后再去執行getUserInfo()方法,是不是覺得這種方式太老實,就好比單身的屌絲,一次只約一個妹子,等被一個妹子拋棄了再去約另一個妹子,這樣子大好年華就這樣浪費了是不,哈哈,所以這肯定在某些場景下不是最優解啊,
下面就來個協程的渣男方式,show code:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
GlobalScope.launch {
val r1 = GlobalScope.async {
getResult1()
}
val r2 = GlobalScope.async {
getResult2()
}
val r = r1.await() + r2.await()
Log.e("lzy", "$r")
}
}
suspend fun getResult2(): Int {
delay(4000)
return 2
}
suspend fun getResult1(): Int {
delay(3000)
return 1
}
}
執行結果:
2021-06-13 05:13:53.432 6448-6475/com.example.b E/lzy: 3
async關鍵字表示并發執行,可以理解為渣男同時約多個妹子,所以得到結果的時間會更快,
值此佳節之際,老夫想吟詩一首:
《辛丑年端午有感》
屈公投江兩千載
汨羅之水天上來
粽葉艾草碧又衰
斗轉星回無可耐
辛丑牛年五月初四筆于姑蘇
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/287367.html
標籤:其他
上一篇:圖解 RabbitMQ 核心概念
