前言笔者在上一篇《百瓶中哨兵的实现》中主要阐述了方案选择和实现两大方面。在本文中,我们主要针对百瓶中哨兵的实现,分析项目实现中遇到的问题。本文分析的主要问题主要有以下几类(FlutterSDK版本为1.22.6,DartSDK版本为2.10.5):NoSuchMethodErrorFlutter官方bug(已修复)StateErrorNetworkError(DNS)NoSuchMethodError问题1问题描述:清单,String等类型数据判断为空,直接使用xxx.isNotEmpty,不判断是否为null,导致NoSuchMethodError:ThegetterisNotEmptywascallednull。问题截图:解决方法://问题代码if(timeEndList.isNotEmpty){...}//解决方法staticboolisNotNullOrEmpty(Iterableiterable)=>iterable!=null&&iterable.isNotEmpty;if(IterableUtils.isNotNullOrEmpty(timeEndList)){...}在进行空判断处理时,需要先判断是否为null,再使用isNotEmpty进行判断,避免此类错误。考虑到我们会用到很多类似的判断,所以我们可以封装同类型的数据判断方法,避免每次使用都要重新写一遍。问题2问题描述:这里是使用Future.wait并发请求多个API,并在第二个API中设置超时时间。因为第二次API请求超时,在后续的响应处理中,没有处理空异常判断,导致获取码失败。问题截图:解决方案://问题代码if(res[1].code==HttpCode.ok){...}//解决方案if(res[1].code==HttpCode.ok){...}当使用Future.wait并发请求多个API时,如果设置了超时处理,要考虑API请求超时失败的问题,尽量避免此类问题。问题3问题描述:当我们需要获取Widget上下文关联的RenderBox的大小或位置时,出现错误。问题截图:解决方法://问题代码最终偏移位置=renderBox.localToGlobal(Offset.zero);ctx.dispatch(MallGoodsDetailActionCreator.setDetailsOffsetYAction(postion.dy));}//解决方案if(IterableUtils.isNotNullOrEmpty(ctx.state.details)==true){WidgetsBinding.instance.addPostFrameCallback((_){finalRenderBoxrenderBox=ctx.state.detailsKey.currentContext.findRenderObject();finalOffsetposition=renderBox.localToGlobal(Offset.zero);ctx.dispatch(MallGoodsDetailActionCreator.setDetailsOffsetYAction(postion.dy));});}出现上述问题的原因是上下文没有关联到我们的状态。如果我们想避免这种情况,我们可以在Widget渲染完成后获取RenderBox的大小或者位置。Flutter官方bug(已修复)问题描述:使用NestedScrollView组件时,由于position.minScrollExtent可以为空,在生产环境运行时偶尔会出现NoSuchMethodErrornested_scroll_view.dartin_NestedScrollCoordinator.hasScrolledBodyNoSuchMethodError:Themethod'>'wascalledon无效的。Receiver:nullTriedcalling:>()该问题已经正式解决并合并到master分支。问题截图:那么这个问题是怎么发生的呢?官方的解释是:scheduleAttachRootWidget会调用_firstBuild并新建一个空像素的_NestedScrollPosition;FocusManager会安排一个微任务;完成firstBuild再刷新microTask,NestedScrollView又脏了;scheduleWarmUpFrame将重建脏节点并触发异常(_NestedScrollPosition仅在布局后可用)。解决方法://问题代码boolgethasScrolledBody{for(final_NestedScrollPositionpositionin_innerPositions){assert(position.minScrollExtent!=null&&position.pixels!=null);如果(position.pixels>position.minScrollExtent){returntrue;}}returnfalse;}//解决方案boolgethasScrolledBody{for(final_NestedScrollPositionpositionin_innerPositions){if(!position.hasContentDimensions||!position.hasPixels){continue;}elseif(position.pixels>position.minScrollExtent){returntrue;}}returnfalse;}StateError问题描述:当我们使用list.firstWhere时,通常会出现BadState:Noelement这样的问题。问题截图:解决方案://问题代码MapgetInitialSkuById(StringskuId,List