记一次排查Flutter中预期外rebuild的过程

664 阅读1分钟

背景

在我的flutter项目中,从A组件导航到B组件后,B组件在软键盘弹起与收起的时候,A组件会不断调用didUpdateWidgetbuild

初步排查

起初以为是路由的问题,经过排查后发现,Navigator确实存在历史问题,会导致oldWidgetrebuild。 在1.17版本之后,这个问题已经被修复了,开发者不再需要额外的工作即可避免。

相关分析

发现端倪

继续排查了很多地方,本以为可能出现问题的菜单组件、MediaQuery的不合适的调用等等,都没有发现问题。 开始从下往上思考:如果组件本身没有调用setState,没有继承InheritedWidget,那发生预期外的生命周期函数调用,一定是它的context在其他地方发生预期外的使用了

找到凶手

搜索A组件里所有用到context的地方,果不其然,凶手找到了:

precacheImage(NetworkImage(Constants.bgUrl), context);

进入precacheImage的源码后,很容易找到context被注册到了MediaQuery.maybeOf,剩下的就很好理解了: MediaQuery继承自InheritedWidget; 软键盘调用时,MediaQueryData会变化,所有通过MediaQuery.maybeOfMediaQuery.of注册的组件都会更新。

总结

  • 深入理解Flutter的生命周期和更新逻辑,在遇到相关的问题时总是能从源码和原理上找到解决办法。
  • 保护好组件的context