Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

27.10. 协程

		
GlobeScope:全局范围,不会自动结束执行。
MainScope:	主线程的作用域,全局范围
lifecycleScope:生命周期范围,用于activity等有生命周期的组件,在onDestroy的时候会自动结束。
viewModelScope:viewModel范围,用于ViewModel中,在ViewModel被回收时会自动结束		
		
		

27.10.1. GlobalScope

27.10.1.1. DefaultDispatcher

				
GlobalScope.launch {
    while (true) {
        delay(1000)
        println("每秒执行一次")
    }
}
				
				

				
	GlobalScope.launch {
        //GlobalScope开启协程:DefaultDispatcher-worker-1
        Log.d(TAG, "GlobalScope开启协程:" + Thread.currentThread().name)
		//子线程中此处不可以做UI操作
		withContext(Dispatchers.Main){
            Toast.makeText(this@MainActivity, "协程中切换线程", Toast.LENGTH_SHORT).show()
        }
    }				
				
				

27.10.1.2. Dispatchers.Main

				
	GlobalScope.launch(Dispatchers.Main) {
        	//GlobalScope开启协程:main
            Log.d(TAG, "GlobalScope开启协程:" + Thread.currentThread().name)
            //可以做UI操作
            Toast.makeText(this@MainActivity, "GlobalScope开启协程", Toast.LENGTH_SHORT).show()
    }				
				
				

27.10.1.3. Dispatchers.IO

				
GlobalScope.launch(Dispatchers.IO) {
    if (AndroidManager.Device.scanMicrophone() && !State.usbMicrophone.get()) {
        aigcSpeech.speaking("蓝牙麦克风连接")
    }
    Log.d(TAG, "Bluetooth connected")
}				
				
				

27.10.1.4. 手动开始协程

				
val job = GlobalScope.launch(start = CoroutineStart.LAZY) {

    Log.w("执行在协程中...")

    delay(1000L)

    Log.w("执行完毕...")
}


job.start()				
				
				

27.10.1.5. 取消协程

				
var job: Job = Job()

...

 GlobalScope.launch(job) {

   Log.w("执行协程...")

    delay(1000L)

    Log.w("执行完毕...")
}


override fun onDestroy() {
    job.cancel()
    super.onDestroy()
}				
				
				

27.10.1.6. 完成回调

				
		val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
            Log.e(throwable.message ?: "Unkown Error")
        }

        val job = GlobalScope.launch(Dispatchers.Main + exceptionHandler) {
            Log.w("执行协程...")

            delay(1000L)

            val num = 9/0

            Log.w("协程执行完毕...")
        }

        job.invokeOnCompletion {
            Log.w("完成或异常的回调")
        }				
				
				

27.10.2. MainScope

			
	MainScope().launch {
            Log.w("执行协程")

            val result = OtherTask {
                async(Dispatchers.IO) {
                    "netkiller"
                }.await()
            }

            Log.w("程执行完毕 $result")
    }
			
			

27.10.3. lifecycleScope

lifecycleScope只能在Activity、Fragment中使用,会绑定Activity和Fragment的生命周期。使用的时候需要导

27.10.3.1. launch

lifecycleScope默认主线程,可以通过withContext来指定线程

				
lifecycleScope.launch {
    // do
    withContext(Dispatchers.IO) {
        // do
    }
}
 
// or
 
lifecycleScope.launch(Dispatchers.IO){
    // do
}
 
// or
 
lifecycleScope.launch {
    whenResumed {
        // do
    }
}
 
// or
 
lifecycleScope.launchWhenResumed {
    // do
}
				
				
				

27.10.3.2. launchWhenResumed

				
	lifecycleScope.launch{
        
        delay(1000L)
        
    }

    lifecycleScope.launchWhenResumed {
        
        delay(3000L)
        
    }
				
				
				

27.10.3.3. 协程中串行任务

			
	private fun serialExecution() {
        lifecycleScope.launch {
            val startTime = System.currentTimeMillis()
            val a = getDataA()
            val b = getDataB()
            val sum = a + b
            //D/MainActivity: serialExecution: sum = 3,耗时:3008
            Log.d(TAG, "serialExecution: sum = $sum,耗时:${System.currentTimeMillis() - startTime}")
        }
    }

    private suspend fun getDataA(): Int {
        delay(1000)
        return 1
    }

    private suspend fun getDataB(): Int {
        delay(2000)
        return 2
    }
			
				

27.10.3.4. 携程并行执行任务

			
private fun parallelExecution(){
        lifecycleScope.launch {
            val startTime = System.currentTimeMillis()
            val a = lifecycleScope.async { getDataA() }
            val b = lifecycleScope.async { getDataB() }
            val sum = a.await() + b.await()
            //D/MainActivity: parallelExecution: sum = 3,耗时:2009
            Log.d(TAG, "parallelExecution: sum = $sum,耗时:${System.currentTimeMillis() - startTime}")
        }
    }
    
    private suspend fun getDataA(): Int {
        delay(1000)
        return 1
    }

    private suspend fun getDataB(): Int {
        delay(2000)
        return 2
    }			
			
				

27.10.3.5. 取消携程

			
private var job: Job? = null
    
job = lifecycleScope.launch {
    ...
}
job?.cancel()
    			
			
				

27.10.4. 

			
CoroutineScope(Dispatchers.IO).launch {
}			
			
			

27.10.5. viewModelScope

27.10.5.1. await()

				
fun getMessageByViewModel() {
    viewModelScope.launch {
        val deferred = async(Dispatchers.IO) { getMessage("netkiller") }
        mMessage.value = deferred.await()
    }
}				
				
				

27.10.6. 协程上下文与继承关系

协程嵌套时取消协程,GlobalScope与MainScope 并不会杯取消。

			
	val job = CoroutineScope(Dispatchers.Main).launch {

	    async(Dispatchers.IO) {
	        Log.w("协程async开始")
	        delay(5000)
	        Log.w("协程async执行完毕")
	    }
	
	    launch {
	        Log.w("协程launch开始")
	        delay(2000)
	        Log.w("协程launch执行完毕")
	    }
	
	    GlobalScope.launch {
	        Log.w("协程GlobalScope开始")
	        delay(3000)
	        Log.w("协程GlobalScope执行完毕")
	    }
	
	    MainScope().launch {
	        Log.w("协程MainScope开始")
	        delay(4000)
	        Log.w("协程MainScope执行完毕")
	    }
	
	}

    override fun onDestroy() {
        super.onDestroy()
        job.cancel()
    }			
			
			

			
	val job = CoroutineScope(Dispatchers.Main).launch {

        async(Dispatchers.IO) {
	        Log.w("协程async开始")
	        delay(5000)
	        Log.w("协程async执行完毕")
	    }
	
	    launch {
	        Log.w("协程launch开始")
	        delay(2000)
	        Log.w("协程launch执行完毕")
	    }
	
	    GlobalScope.launch {
	        Log.w("协程GlobalScope开始")
	        delay(3000)
	        Log.w("协程GlobalScope执行完毕")
	    }

        MainScope().launch(job!!) {
            Log.w("协程MainScope开始")
            delay(4000)
            Log.w("协程MainScope执行完毕")
        }

    }

    override fun onDestroy() {
        super.onDestroy()
        job.cancel()
    }