首页 文章

颤动:从子节点检索顶级状态返回null

提问于
浏览
2

我正在尝试使用.of()方法获取我的应用程序的顶级状态,类似于Scaffold.of()函数 . 这是(剥离)代码:

class IApp extends StatefulWidget {    
  @override
  IAppState createState() => new IAppState();

  static IAppState of(BuildContext context) =>
    context.ancestorStateOfType(const TypeMatcher<IAppState>());
}

该应用程序使用runApp(新IApp)启动

此Widget创建一个HomePage:

@override
  Widget build(BuildContext context) {
    return new MaterialApp(
      // ommitted: some localization and theming details
      home: new HomePage(),
    );
  }

然后,我尝试从HomePage(StatefulWidget本身)访问状态:

@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 in the same file 的代码作为IApp放置时,代码可以工作,但是作为一个额外的类 . 但是,当我将HomePage in a separate file (main.dart和homepage.dart相互导入)放置时,IApp.of(context)的返回值为null .

是什么导致这个?我该如何解决?

1 回答

  • 10

    TDLR :仅使用导入文件

    import 'package:myApp/path/myFile.dart';
    

    从来没有

    import './myFile.dart';
    

    这是由于飞镖如何解决进口问题 .

    您可能只有一个源文件,但在构建期间,存在某种重复项 .

    假设你正在研究'myApp' . 要导入文件,您可以同时执行以下操作:

    • import 'relativePath/myFile.dart'

    • import 'package:myApp/path2/myFile.dart'

    你认为他们指的是同一个文件吗?但不是 . 其中一个将指向原始来源 . 而另一个将指向用于构建的临时文件 .

    当你开始混合两种解决方案时,问题就来了 . 因为对于编译器,这两个文件是 different . 这意味着从 package:myApp/IApp 导入的 IApp 不等于从 relativePath/myApp/IApp 导入的相同 IApp

    在您的情况下,您在窗口小部件树中插入 IApp 来自 pakage:path ,但您的 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
    

    剧透:结果是假的

相关问题