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:pathIApp,但您的IApp.of(context) 使用IAppState 在本地解析。 它们都有不同的 runtimeType。因此const TypeMatcher&lt;IAppState&gt;() 将不匹配。您的函数将返回 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的主要内容,如果未能解决你的问题,请参考以下文章

从子进程中检索 PID 和退出状态

Swift UI 如何从子视图中检索状态

React - 在下拉选择中将状态从子级传递给父级

我可以使用react中的useEffect挂钩从子级设置父级的状态

我如何将 useState 值从子级传递给父级

禁用 Flutter Hero 反向动画