Flutter输入:相对路径还是包?

z9zf31ra  于 2023-01-02  发布在  Flutter
关注(0)|答案(6)|浏览(174)

在Flutter中,为了导入我们自己包的lib目录中的库,我们应该使用相对导入吗

import 'foo.dart'

还是包导入?

import 'package:my_app/lib/src/foo.dart'

Dart指导原则主张使用相对导入:
在您自己的软件包的lib目录中导入库时,首选相对路径。
Provider包要求总是使用包导入:

  • 始终使用包导入。例如:import 'package:my_app/my_code.dart';

除了简洁之外还有什么不同吗?为什么包导入会比相对导入减少错误?

pbpqsu0x

pbpqsu0x1#

根据相同的Dart指南,他们进一步给予了相对进口的原因:
没有什么深刻的理由去偏爱前者--它只是更短,而且我们希望保持一致。
就我个人而言,我更喜欢绝对方法,尽管它更冗长,因为它意味着当我从不同的dart文件(在其他文件夹中)导入时,我不必计算要导入的文件相对于当前文件的位置。
我有两个dart文件,位于不同的文件夹级别,需要导入themes/style.dart
一个是widgets/animation/box_anim.dart,其中相对路径导入为:

import '../../themes/style.dart';

另一个是相对导入的screens/home_screen.dart

import '../themes/style.dart';

这可能会让人感到困惑,所以我发现在两个文件中使用绝对值更好,保持一致:

import 'package:myapp/themes/style.dart';

并且自始至终坚持这条规则。所以,基本上,无论你使用什么方法-一致性都是关键!
Linter for Dart包也有something to say about this,但更多的是关于在“/lib”文件夹中混合的不要
避免对lib/中的文件进行相对导入。
当混合使用相对导入和绝对导入时,可能会混淆同一个成员以两种不同的方式导入。避免这种情况的一个简单方法是确保没有路径中包含lib/的相对导入。

ki1q1bka

ki1q1bka2#

TLDR;选择您喜欢的选项,请注意,官方有效 dart 指南中建议使用prefer_relative_imports

  • 首先,如this answer中所述,Provider不再重新命令包导入。*

Dart linter提供了一个规则列表,其中包括一些预定义的规则集:

导入规则

关于进口,实际上有两个以上的对立规则:

以下两个是你提到的:

  • prefer_relative_imports,未在预定义的规则集中启用,但建议在Effective Dart guide中使用,以避免:
  • always_use_package_imports,没有在预定义的规则集中启用。这意味着由您和您的首选项来启用它(小心,它与前一个规则不兼容)

我应该选择哪一个?

选择你想要的规则!它不会导致任何性能问题,而且没有规则会比其他规则减少错误。只要选择一个规则,使你的导入在所有项目中保持一致,感谢Dart Linter。
我个人更喜欢使用prefer_relative_imports,因为它是由 dart 团队推荐的,this VSCode extension可以自动修复和排序我的导入。

monwx1rj

monwx1rj3#

提供程序不再需要包导入。
这是一个旧Dart错误的变通方案:Flutter:从子级检索顶级状态返回null
DR,通过混合相对和绝对导入,有时Dart创建了类定义的副本。
这就引出了一句荒谬的话:

import 'package:myApp/test.dart' as absolute;
import './test.dart' as relative;

void main() {
  print(relative.Test().runtimeType == absolute.Test().runtimeType); // false
}

由于provider依赖于runtimeType来解析对象,因此此bug使provider在某些情况下无法获取对象。

v09wglhw

v09wglhw4#

我对这个主题的看法是,当你决定重组/清理你的项目结构时,绝对(package:my_app/etc/etc2...)导入比相对(../../etc/etc2...)导入带来的麻烦要少得多,因为无论何时你将一个文件从一个目录移动到另一个目录,你都改变了这个文件使用的每个相对导入的“起点”,从而破坏了移动文件内的所有相对导入。
出于这个原因,我个人总是更喜欢绝对路径而不是相对路径

knsnq2tg

knsnq2tg5#

这个问题已经有了很好的答案,但是我想提一下一个非常烦人而且很难发现的问题,我在单元测试中遇到过这个问题,它是由相对导入引起的。
异常捕获预期块的expect失败指示符

expect(
  () => myFunction,
  throwsA(isA<InvalidUserDataException>())
);

显示actual结果与expected结果完全相同,并且没有说明失败的原因。
经过大量的反复试验,问题是因为预期的InvalidUserDataException(一个定制类)以RELATIVE格式与PACKAGE格式导入到测试文件中。
为了找到这个,我不得不将这个测试文件与另一个使用完全相同的异常预期器的测试文件进行并排、逐行、逐个调用的比较(幸运的是,我们有这个),碰巧,我滚动到这个文件导入的顶部,看到蓝色下划线写着prefer relative imports to /lib directory
不,他们不是首选;它们是必要的,因为当我将其更改为PACKAGE(绝对)导入时,一切突然开始工作。
我从中学到的是:* 对测试文件(lib目录以外的文件)使用绝对导入 *

  • 例如src/test/main_test.dart内部
      • 不要**:使用import '../lib/main.dart'
      • 执行**:使用package:my_flutter_app/main.dart

也许其他人已经知道这一点,但我不知道,我也找不到任何关于这个问题的在线搜索,所以我想我会分享我的经验,可能会帮助其他人谁陷入了这个问题。
有人知道为什么会这样吗?
编辑:在上下文中,这发生在使用带有Sound Null Safety的Flutter 2.1.4(稳定)时

rdlzhqv9

rdlzhqv96#

您是否使用集成测试?

如果答案是肯定的,那么在大多数情况下,你需要使用包导入。当你试图在物理设备上运行集成测试时,任何相对导入都不能找到它们要找的东西。
示例:https://github.com/fluttercommunity/get_it/issues/76
您可以使用以下两条规则在项目中强制执行包导入:

我也更喜欢包导入,因为即使在重新排列文件和文件夹时,它们也会粘在一起。相对导入经常会中断,必须删除它们并重新导入令人不快的依赖关系是一件痛苦的事情。

相关问题