Flutter Exception降到万分之几的秘密

Flutter exception

闲鱼技术团队于2018年上半年率先引入了Flutter技术实现客户端开发,到目前为止成功改造并上线了复杂的商品详情和发布业务。随着flutter比重越来越多,我们开始大力治理flutter的exception,起初很长一段时间内闲鱼内flutter的exception率一直在千分之几左右。经过我们的整理和解决,解决了90%以上的flutter exception。

我们对exception进行了归类,大头主要分为两大类,这两大类堆栈数量很多,占到整体90%左右:

第一大类的堆栈都指向了setstate

#0      State.setState (package:flutter/src/widgets/framework.dart:1141)
#1      _DetailCommentWidgetState.replyInput.<anonymous closure>.<anonymous closure> (package:fwn_idlefish/biz/item_detail/fx_detail_comment.dart:479)
#2      FXMtopReq.sendReq.<anonymous closure> (package:fwn_idlefish/common_lib/network/src/mtop_req.dart:32)
#3      NetService.requestWithModel.<anonymous closure> (package:fwn_idlefish/common_lib/network/src/net_service.dart:58)
#4      _rootRunUnary (dart:async/zone.dart:1132)
#5      _CustomZone.runUnary (dart:async/zone.dart:1029)
#6      _FutureListener.handleValue (dart:async/future_impl.dart:129)

第二大类堆栈都与buildContext相关

#0      Navigator.of (package:flutter/src/widgets/navigator.dart:1270)
#1      Navigator.pop (package:flutter/src/widgets/navigator.dart:1166)
#2      UploadProgressDialog.hide (package:fwn_idlefish/biz/publish/upload_progress_dialog.dart:35)
#3      PublishSubmitReducer.doPost.<anonymous closure> (package:fwn_idlefish/biz/publish/reducers/publish_submit_reducer.dart:418)
<asynchronous suspension>
#4      FXMtopReq.sendReq.<anonymous closure> (package:fwn_idlefish/common_lib/network/src/mtop_req.dart:32)
#5      NetService.requestWithModel.<anonymous closure> (package:fwn_idlefish/common_lib/network/src/net_service.dart:58)
#6      _rootRunUnary (dart:async/zone.dart:1132)
#7      _CustomZone.runUnary (dart:async/zone.dart:1029)

第一类明显与element和sate的生命周期有关。第二类与buildContext有关。

buildContext是什么?

下面是一段state中获取buildContext的实现

Element get _currentElement => _registry[this];
BuildContext get currentContext => _currentElement;

很明显buildContext其实就是element实例。buildContext是一个接口,element是buildContext的具体实现。所以上面的exception都指向了flutter element和state的生命周期。

Flutter 生命周期

state生命周期

bb

element与state生命周期

element是由widget createElement所创建。state的生命周期状态由element调用触发。

bb

最核心的是在new elment的时候element的state的双向绑定正式建立。在umount的时候element和state的双向绑定断开。

activity生命周期与state关系

flutter提供WidgetsBindingObserver给开发者来监听AppLifecycleState。 AppLifecycleState有4种状态:

 
 
  1. 1.resumed

  2. 界面可见,比如应用从后台到前台


  3. 2.inactive

  4. 页面退到后台或者弹出dialog等情况下

  5. 这种状态下接收不到很任何用户输入,但是还会有drawframe的回调


  6. 3.paused

  7. 应用挂起,比如退到后台。进入这种状态代表不在有任何drawframe的回调


  8. 4.suspending

  9. ios中没用,puased之后进入的状态,进入这种状态代表不在有任何drawframe的回调

看下android生命周期和appLifecycleState、state关系,

1.创建

bb

2.按home键退到后台

bb

3.从后台回到前台

bb

4.back键退出当前页面(route pop)

bb

5.back键退出应用

bb常见的exception例子

工程开发中容易忽略state的dispose状态

看一段例子:

bb

这个例子可能会在某些情况下excetion。

在state dispose后,element会和state断开相互引用,如果在这个时候开发者去拿element的位置信息或者调用setstate 刷新布局时就会报异常。

最常见的是在一些timer、animate、网络请求等异步逻辑后调用setstate导致的excetion。安全的做法是在调用setstate前判断一下state是否是mounted状态。如下:

bb

buildContext使用错误

看一段错误使用buildcontext例子:

bb

上面的错误在于在跨堆栈使用了buildcontext。由于outcontext的生命周期与buttomcontext不一致,在弹出bottomsheet的时候outcontext可以已经处于umount或者deactivite。上面例子正确的做法是使用bottomcontext获取focusScopeNode。

我们在跨堆栈传递参数(如bottomsheet、dialog、alert、processdialog等)场景时特别要注意buildcontext的使用。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/69900359/viewspace-2286381/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/69900359/viewspace-2286381/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值