Flutter:从子级检索***状态返回null
Posted
技术标签:
【中文标题】Flutter:从子级检索***状态返回null【英文标题】:Flutter: Retrieving top-level state from child returns null 【发布时间】:2018-04-17 16:46:44 【问题描述】:我正在尝试使用类似于 Scaffold.of() 函数的 .of() 方法获取我的应用程序的***状态。这是(精简的)代码:
class IApp extends StatefulWidget
@override
IAppState createState() => new IAppState();
static IAppState of(BuildContext context) =>
context.ancestorStateOfType(const TypeMatcher<IAppState>());
应用程序使用 runApp(new IApp) 启动
这个小部件创建一个主页:
@override
Widget build(BuildContext context)
return new MaterialApp(
// ommitted: some localization and theming details
home: new HomePage(),
);
然后,我尝试从 HomePage(StatefulWidget 本身)访问 State:
@override
Widget build(BuildContext context)
return new Scaffold(
// ommited: some Scaffold properties such as AppBar
// runtimeType not actual goal, but just for demonstration purposes
body: new Text(IApp.of(context).runtimeType.toString()),
);
奇怪的是,当我将 HomePage 的代码放在与 IApp 相同的文件 中时,代码仍然有效,但只是作为一个额外的类。但是,当我将 HomePage 放在单独的文件中(main.dart 和 homepage.dart 相互导入)时,IApp.of(context) 的返回值为 null。
这是什么原因造成的?我该如何解决?
【问题讨论】:
愚蠢的问题,这可能无关紧要,但是在导入文件时,您使用的是相对路径(“./homepage.dart”)还是绝对路径(“package:my_package/homepage.dart”) ? 我使用的是绝对路径,比如 package:my_package/etc/file.dart 我很久以前有过类似的错误,我不确定但使用相对路径解决了它,或者它是别的东西^^ 这确实解决了它,非常感谢!我仍在等待“正确”的答复(至于是什么原因造成的,以及为什么相对进口会修复它),所以我还没有将问题标记为已回答。不过还是谢谢! 【参考方案1】:TDLR:仅使用导入文件
import 'package:myApp/path/myFile.dart';
从来没有
import './myFile.dart';
这是由于 dart 如何解析导入。
您可能只有一个源文件,但在构建过程中,会有一些重复。
假设您正在开发“myApp”。要导入文件,您可以同时执行以下操作:
import 'relativePath/myFile.dart'
import 'package:myApp/path2/myFile.dart'
您会认为它们指向同一个文件,对吧? 但不是。其中之一将指向原始来源。而另一个将指向用于构建的临时文件。
当您开始混合使用这两种解决方案时,问题就来了。因为对于编译器来说,这两个文件不同。这意味着从package:myApp/IApp
导入的IApp
不等于从relativePath/myApp/IApp
导入的相同IApp
在您的情况下,您在小部件树中插入了来自pakage:path
的IApp
,但您的IApp.of(context)
使用IAppState
在本地解析。
它们都有不同的 runtimeType。因此const TypeMatcher<IAppState>()
将不匹配。您的函数将返回 null。
有一种非常简单的方法可以测试这种行为。
创建一个test.dart
文件,仅包含
class Test
然后在您的 main.dart
添加以下导入:
import 'package:myApp/test.dart' as Absolute;
import './test.dart' as Relative;
您最终可以通过以下方式进行测试:
new Relative.Test().runtimeType == new Absolute.Test().runtimeType
剧透:结果是假的
【讨论】:
我使用了绝对导入,但这个问题仍然存在。还有其他线索吗? 其实我很确定情况并非如此。 Dart 能够规范化相对路径和绝对路径。几周前修复了一个与 Flutter 相关的问题,该问题破坏了这种规范化,因为入口点文件位于lib/
而不是 bin/
它最初在 Dart 中的设计方式。我已经看到它提到,当文件名中使用大写字母时,Windows 上仍有可能会破坏这一点,但我没有使用 Windows 手没有经历过这种情况。
@GünterZöchbauer 我敢肯定这在某些时候是真的。但这可能在此期间已修复,我还没有检查过
虽然这是真的,但只有在使用相对导入时才使用 lib/main.dart
。如果这个文件只包含包导入,那么你可以在其他任何地方混合相对和包导入。【参考方案2】:
现在你可以使用相对路径了。
您可以按照 Remy 两年前的建议进行验证:
Relative.Test().runtimeType == Absolute.Test().runtimeType
剧透:结果为真
【讨论】:
以上是关于Flutter:从子级检索***状态返回null的主要内容,如果未能解决你的问题,请参考以下文章