Kotlin 之 协程,微信小程序趋势及前景

        Log.v("zx", "结果:$result")

    }

打印:

com.z.zjetpack V/zx: sleep

com.z.zjetpack V/zx: sleep

com.z.zjetpack V/zx: 结果:默认数据




如上,如果在1秒内完成了,那么结果为 完成,如果没做完会返回结果null,为null即显示默认数据



[]( )协程的异常处理

---------------------------------------------------------------------



runBlocking {

        val job1 = launch {

            try {

                throw NullPointerException()

            } catch (e: Exception) {

                log("launch,$e.toString()")

            }



        }



        val job2 = async {

            try {

                throw NullPointerException()

            } catch (e: Exception) {

                log("async,$e.toString()")

            }

        }

        job2.await()



    }



异常的传播特性是:当一个协程生成异常,它会传给它的父级,之后父级会取消它自己的子级,然后取消它自己,最后将异常传给它的父级。  

那么如果我们想要一个子协程发送异常不影响其他协程怎么办呢?  

答:使用SupervisorJob和SupervisorScope



使用SupervisorJob时,一个子协程的运行失败不会影响到它的子协程。SupervisorJob不会传播异常给它的父级,他会让子协程自己处理异常



使用CoroutineExceptionHandler捕获协程异常



val handle = CoroutineExceptionHandler { coroutineContext, throwable ->

        Log.v("zx","$throwable")

    }



    CoroutineScope(Dispatchers.Main).launch(handle) {

        throw NullPointerException()

    }



Android种全局异常处理  

全局异常处理器可以获取到所有协程未处理的未捕获异常,不管它并不能对异常进行捕获,虽然不能阻止程序崩溃,全局异常处理器在程序调试和异常上报场景有很大作用。  

我们需要在app/src/main下面创建一个resources/META-INF/services目录并在其中创建一个名为kotlinx.coroutines.CoroutineExceptionHandler的文件,文件内容就是异常处理器的全类名。



![在这里插入图片描述](https://img-blog.csdnimg.cn/a194c4dd63aa490fae9a495510d114f3.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWlpfR08=,size_20,color_FFFFFF,t_70,g_se,x_16)



package com.z.zjetpack.coroutine

import android.util.Log

import kotlinx.coroutines.CoroutineExceptionHandler

import kotlin.coroutines.CoroutineContext

class GException:CoroutineExceptionHandler {

override val key = CoroutineExceptionHandler



override fun handleException(context: CoroutineContext, exception: Throwable) {

    Log.v("zx","异常信息:$exception")

}

}




kotlinx.coroutines.CoroutineExceptionHandler文件中的内容为:包名+类名  

com.z.zjetpack.coroutine.GException  

![在这里插入图片描述](https://img-blog.csdnimg.cn/199f7f8a2e704dd79e007075f8191c23.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWlpfR08=,size_20,color_FFFFFF,t_70,g_se,x_16)



### []( )取消与异常



*   取消与异常紧密相关,协程内部使用CancellationException来取消,这个异常会被忽略,当子协程被取消时,不会取消它的父协程



    runBlocking {

        val job = launch {

            val childjob = launch {

                try {

                    delay(Long.MAX_VALUE)

                }finally {

                    Log.v("zx","子协程被取消了")

                }

            }

            //出让执行权,让子协程有机会执行

            yield()

            Log.v("zx","开始取消")

            childjob.cancelAndJoin()

            //childjob.cancel()

            //没有AndJoin就会继续往下执行

            //Log.v("zx","取消中。。。")

            yield()

            Log.v("zx","父协程还没被取消")



            //父协程中释放资源

            ...

        }

        job.join()

    }

打印:

com.z.zjetpack V/zx: 开始取消

com.z.zjetpack V/zx: 子协程被取消了

com.z.zjetpack V/zx: 父协程还没被取消




*   如果一个协程遇到了CancellationException以外的异常,它将使用该异常取消它的父协程。当父协程的所有子协程都结束后,异常才会被父协程处理。



    runBlocking {



        val handle = CoroutineExceptionHandler { coroutineContext, throwable ->

            Log.v("zx","捕获异常:$throwable")

        }



        val job1 = GlobalScope.launch(handle) {

            val child1 = launch {

                try {

                    delay(Long.MAX_VALUE)

                }finally {

                    //这里如果要执行挂起函数要用NonCancellable

                    withContext(NonCancellable) {

                        Log.v("zx","child1子协程已被取消,但异常未被处理")

                        delay(100)

                        Log.v("zx","child1子协程已完成")

                    }



                }

            }

            val child2 = launch {

                delay(10)

                Log.v("zx","child2 抛出异常")

                throw NullPointerException()



            }

        }

        job1.join()

    }

打印:

com.z.zjetpack V/zx: child2 抛出异常

com.z.zjetpack V/zx: child1子协程已被取消,但异常未被处理

com.z.zjetpack V/zx: child1子协程已完成

com.z.zjetpack V/zx: 捕获异常:java.lang.NullPointerException




### []( )异常聚合



当协程的多个子协程因为异常而失败时,一般取第一个异常处理,在第一个异常后发生的所有异常都会绑定到第一个异常上。



    runBlocking {



        val handle = CoroutineExceptionHandler { coroutineContext, throwable ->

            Log.v("zx", "其他异常:${throwable.suppressed.contentToString()}")

            Log.v("zx", "当前捕获异常:$throwable")

        }



        GlobalScope.launch(handle) {

            launch {

                try {

                    delay(Long.MAX_VALUE)

                } finally {

                    throw NullPointerException()

                }



            }

            launch {

                try {

                    delay(Long.MAX_VALUE)

                } finally {

                    throw IndexOutOfBoundsException()

                }



            }

            launch {

                delay(100)

                throw ArithmeticException()

            }

        }

    }

打印:

其他异常:[java.lang.NullPointerException, java.lang.IndexOutOfBoundsException]

当前捕获异常:java.lang.ArithmeticException




[]( )(三)Flow异步流

========================================================================



[]( )flow介绍

--------------------------------------------------------------------



挂起函数可以异步返回单个值,那如何**异步多次**返回多个值呢?  

使用flow,flow的特点:



*   flow{…}块中的代码可以挂起

*   使用flow,suspend修饰符可以省略

*   流使用emit函数发射值

*   流使用collect的函数收集值

*   flow类似冷流,flow中代码直到流被收集(调用collect)的时候才运行,类似lazy,什么时候用,什么时候执行。

*   流的连续性:流收集都是按顺序收集的

*   flowOn可更改流发射的上下文,即可以指定在主线程或子线程中执行

*   与之相对的是热流,我们即将介绍的 StateFlow 和 SharedFlow 是热流,在垃圾回收之前,都是存在内存之中,并且处于活跃状态的。



//使用flow,suspend修饰符可以省略

fun doflow() = flow<Int> {

    for (i in 1..5) {

        //这里是挂起,不是阻塞

        delay(500)

        emit(i)

    }

}.flowOn(Dispatchers.IO)

//调用

runBlocking {

        doflow().collect {

            log("value=$it")

        }

    }

打印(多次返回多个值)

com.z.zjetpack V/zx: value=1

com.z.zjetpack V/zx: value=2

com.z.zjetpack V/

  • 13
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值