【Flutter 问题系列第 76 篇】在 Flutter 中 Builder 组件的作用以及如何解决 Scaffold.of 找不到上下文问题的解决文案

这是【Flutter 问题系列第 76 篇】,如果觉得有用的话,欢迎关注专栏。

一:问题描述

写这篇博客的初衷是因为前几天面试时,面试官问了一个这样的问题,很遗憾之前我用 Builder 组件只是用它在函数体内定义一些变量,处理逻辑,返回不同的组件。鉴于当时这个问题没有答好,所以研究了 Builder 组件后写下了这篇博客,下面是博客正文。

先来看一段代码,如下图所示

在这里插入图片描述

点击按钮后,会报如下图所示的错误。

在这里插入图片描述

主要报错信息是 Scaffold.of() called with a context that does not contain a Scaffold ,意思是使用不包含脚手架的上下文调用了 Scaffold.of() 。

为什么会报这个错误呢?这里先卖个关子,此时先按照报错内容中给出的第一种解决文案试一试,先给按钮组件外层套一个 Builder 组件试试。

二:解决方案一,使用 Builder 组件

给按钮组件外部套一个 Builder 组件,如下图所示

在这里插入图片描述

此时再点击按钮后不再报错了,也正常返回了结果。

问题是解决了,可只是套了一个 Builder 组件就正常了,这是为什么呢?

三:源码分析

我们先来看一下 Builder 类的源码,如下图所示

在这里插入图片描述

源码很简单,可以看到 Builder 是一个继承于 StatelessWidget 的组件,通过 BuildContext 对象来构建 Widget 对象。

有一个必传参数 builder,其定义如下图所示

在这里插入图片描述

可以看到,自身只是将当前的 context 对象作为回调传递了出去,然后让开发者根据回调中的 context 进行组件的构建。

原来使用了 Builder 组件后再调用 Scaffold.of() 方法,用的 context 是自己的,而不是根组件的了。

再来看下 of 方法的部分代码,如下图所示

在这里插入图片描述

findAncestorStateOfType 会根据传入的上下文,获取指定类型祖先的 State,如果找到则返回 ScaffoldState 的结果,反之就会拋出如上的异常信息。

重点来了,拿小本本记一下

  • 未加 Builder 组件前,调用 Scaffold.of(context) ,此时用的上下文是根组件的 context,而根组件的 context 是传入进来的,of 方法向上查找不到 Scaffold 的实例。
  • 加了 Builder 组件后,在 Builder 组件内部调用了 Scaffold.of(context),此时是根据 Builder 中的 context 向上查找最近的祖先,可以找到 Scaffold 的实例,所以没有再拋出异常。

说了这么多,简单来说其实就一句话,就是调用 context 处理相关逻辑时,是否可以找到对应组件的实例,找不到就拋出异常。

四:解决文案二,使用自定义组件

知道为什么使用 Builder 组件后异常消失了,那自定义一个小组件不就是一样的道理了。

如下图所示

在这里插入图片描述

当然,此时点击按钮不会拋出异常,也可以正常返回结果。

五:解决文案三,使用 GlobalKey

也可以使用 GlobalKey 的方式实现,如下图所示

在这里插入图片描述

根据全局 key 的当前状态 currentState 强转为 ScaffoldState 即可,也可以正常返回结果。

ok,关于 Flutter 中 Builder 组件的作用以及如何解决 Scaffold.of 找不到上下文的解决文案便说到这里。

你的问题得到解决了吗?欢迎在评论区留言。

赠人玫瑰,手有余香,如果觉得文章不错,希望可以给个一键三连,感谢。


结束语

Google 的 Flutter 越来越火,截止 2023年3月12日 GitHub 标星已达 151K,Flutter 毅然是一种趋势,所以作为前端开发者,没有理由不趁早去学习。

无论你是 Flutter 新手还是已经入门了,不妨先点个关注,后续我会将 Flutter 中的常用组件(含有源码分析、组件的用法及注意事项)以及可能遇到的问题写到 CSDN 博客中,希望自己学习的同时,也可以帮助更多的人。

猜你喜欢

转载自blog.csdn.net/qq_42351033/article/details/129473762