从 0 开始设计 Flutter 独立 APP | 第三篇: 一劳永逸解决全局 BuildContext 问题
鉴于Flutter的高性能渲染、跨平台、多端一致性等优势,闪点清单在移动端APP上,使用了完整的Flutter框架来开发。既然是完整APP,架构搭建完全不受历史Native APP的影响,没有历史包袱的沉淀,设计也能更灵活和健壮。
全局BuildContext
,几乎是所有Flutter开发者的一个痛点。这个痛点有多痛呢?我们来列举一下场景:
路由跳转、弹窗、媒体查询,全部依赖于BuildContext,如果在Service层(或其他非UI层)做这些操作,必须要逐层传递正确的BuildContext实例。
依赖于BuildContext的逻辑,必须写在某一个页面的Widget初始化中,否则无法拿到正确的BuildContext;而一些全局初始化的逻辑必须要写在某一个页面里,而如果首次唤起的不是这个页面,需要手动保证初始化逻辑不出问题。
获取当前前台页面的路由,可以用ModalRoute对象,但必须拿到目标页面的BuildContext才可以,Navigator的BuildContext是拿不到的。
MediaQuery、Navigator、Overlays的BuildContext不是一个,不能用错。
Flutter绝大部分第三方UI库是依赖于BuildContext,意味着你必须要在APP初始化后才能使用这些库,即使是toast这样的工具UI。
等等等等......
社区推荐方案
在Android中,我们可以用getApplicationContext
解决全局context问题,Flutter官方并没有提供建议的方案,不过社区有一些推荐的解决方案,比如使用GlobalKey的方案:
首先我们定义一个GlobalKey
,然后在初始化MaterialApp
的时候传入navigatorKey
,然后我们在需要使用路由跳转的地方,不使用原始的方式,而使用navigatorKey来调用:
社区推荐方案的问题
看起来上述方案好像可以解决问题,但是目前只能解决页面路由跳转问题,而如果使用Overlays(比如Dialog)、MediaQuery等就会出现问题了,error提示context不合法:
而直接使用navigatorKey.currentState.context
获取全局context也会出现同样的error。
OneContext解决方案
在尝试众多方案都失败后,我们仍然在继续寻找更好的方案,最终找到了OneContext方案,仓库地址: one_context。
OneContext是一个非常新的库,2020年5月初才发第一个版本,目前还未发1.0版本。不过API的完成度还是很高的。
使用方式
使用OneContext,首先我们需要在MaterialApp中配置OneContext:
然后,需要使用context的地方,全部通过OneContext来调用:
路由跳转
Overlays操作
主题和媒体查询
主题模式修改
原理分析
从OneContext配置中,可以看出来,OneContext最关键的一句配置是OneContext().builder
,我们点进去看源码:
从源码中我们可以看到:
在builder函数中,OneContext重写了Widget结构中的MediaQuery和Navigator的初始化配置,并在每个页面的Widget外层包了一层
OneContextWidget
,然后就可以在OneContextWidget拿到内层context,这个context可以用于绝大部分场景。在OneContextWidget中,提供了
Overlay
的常用方法,并绑定了内部的context对象,从而解决Overlay的context获取问题。
OneContextWidget
在每次build时,会更新全局context:
接入风险
接入OneContext后,务必对原有业务流程进行完成回归,尤其是页面返回逻辑(我们就被坑了一次,
Navigator.pop
无法正确关闭Dialog
)页面返回逻辑,Overlay的场景,需要使用
OneContext().popDialog()
代替Navigator.pop
,切记切记。
总结
到目前我们解决了Flutter全局BuildContext的问题,但这其实并不应该是最终的方案,OneContext
是一个侵入性比较高的方案,Flutter官方应该提供更好的方案来解决这个问题。
讲到这里,还并没有完成基础框架的搭建,后面我们会讲解更多的Flutter架构设计内容,比如:通知、分享、UI设计等等。
持续分享闪点清单在Flutter上的开发经验。闪点清单,一款悬浮清单软件:
版权声明: 本文为 InfoQ 作者【渔子长】的原创文章。
原文链接:【http://xie.infoq.cn/article/d384d3200f010a5a66e3c485f】。文章转载请联系作者。
评论