颤动:从子级返回顶级状态返回null

时间:2017-11-05 12:12:34

标签: dart flutter

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

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

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

使用runApp(新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。

是什么原因引起的?我该如何解决?

2 个答案:

答案 0 :(得分:13)

TDLR :仅使用

导入文件
import 'package:myApp/path/myFile.dart';

从不使用

import './myFile.dart';

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

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

让我们说你正在研究myApp&#39;。要导入文件,您可以同时执行以下操作:

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

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

当您开始混合两种解决方案时,问题就出现了。因为对于编译器,这两个文件不同。这表示从IApp导入的package:myApp/IApp不等于从IApp导入的relativePath/myApp/IApp

在您的情况下,您在窗口小部件树中插入了来自IApp的{​​{1}},但您的pakage:path使用IApp.of(context)已在本地解析。 它们都有不同的runtimeType。因此IAppState无法匹配。并且您的函数将返回null。

测试此行为是一种非常简单的方法。 创建仅包含

const TypeMatcher<IAppState>()文件
test.dart

然后在class Test { } 添加以下导入:

main.dart

您最终可以通过执行以下操作来测试:

import 'package:myApp/test.dart' as Absolute;
import './test.dart' as Relative;

剧透:结果是假的

答案 1 :(得分:1)

现在您可以使用相对路径了。

您可以按照雷米两年前的建议进行验证:

Relative.Test().runtimeType == Absolute.Test().runtimeType

剧透:结果为真