https://www.qiyuandi.com/zhanzhang/zonghe/16693.html
这样写platform channel调用并处理异常的代码,有啥问题?
结果往下看:
代码这样直接用try-catch是无效的,不会走到catch块里!且日志里直接显示Unhandled Exception。
因为channel.invokeMethod是一个异步函数,它的返回值是Future:
更多的分析和正确的写法,请看下文。
最佳实践
- 如果使用了await调用了异步函数(返回Future的函数)并且需要做异常处理,在await外面直接try-catch即可
- 如果没有使用await调用了异步函数(返回Future的函数)并且需要做异常处理,千万不要直接try-catch(否则起不到捕获作用,代码会继续误导下一个人),需要使用
onError或者catchError做对应的处理或者re-throw。
背景
先说下这个问题的背景是,调查了一个webview_flutter和一个settings插件的platform调用异常问题,两个异常很类似:
有如下异常:
这应该是一个类似于上面提到的 channel.invokeMethod('evaluateJavascript') 的调用。在查看webview plugin部分出现的invokeMethod的dart代码后,看到代码是这样写的:
evaluateJavascript里面的实现是这样
第一反应,? try-catch 为什么没有catch住异常呢?
做了5个测试
看下面的5种情况的异常处理的测试代码,前提是:getPlatformVersion故意弄成了一个没有注册过的channel method的名字,一定会抛出MissingPluginException异常。
那么猜想5种写法分别会得到什么结果?
结果是(看图):

也就是:
- 第1种,是错误的,catch块永远不会调用到,且future变量的type是
Future<dynamic> - 第2种,是正确的,拿到future对象并对它做了await操作,此时catch可以正常捕获
- 第3种,是正确的,onError是Future的一个方法,可以在内部抛出异常的时候,转成异常处理的lambda函数,并且此时这个异常从unhandled转换成handled状态
- 第4种,是不推荐的,不用await且不做异常处理,直接在日志中抛出如下异常:
并且注意到,这种异常的里面,是没有调用来源信息的(没有调用地方的行号,只有platform_channel.dart的行号)

- 第5种,是不推荐的,使用了await但是没有onError或者try-catch做异常处理,遇到异常可能日志会出现如下异常信息:

注意到这种使用了await的情况下,里面是有嵌套的异步调用信息的。这里对于解决Dart异常会有很大帮助。
解决方法
- webview_flutter的Dart异常可以改成:
注:在evaluateJavascript的这里的场景下catchError暂时不做其他处理;
在其他场景下,可以根据具体exception的类型做区分,并相应处理或者re-throw出来。
浙公网安备 33010602011771号