如何在flutter中组织包内的dart文件

问题描述 投票:0回答:3

我是使用 flutter 编程的新手,我想开发一个包含几个屏幕的小项目:登录、主页、设置、用户、购买历史记录等。

我需要组织包内的代码,以便于阅读。

如果我开发一个Android应用程序,我会创建一些包:model、activity、fragment、util等。如果我创建一个LoginActivty,我会把它放在activity包中。如果我创建一个用户模型,我会将其放入模型包中。等等。

那么如果我开发一个 flutter 项目,我应该将迄今为止创建的所有文件放在哪里?

目前我只创建了模型包。

flutter dart
3个回答
8
投票

首先,在 Flutter 中我们不直接处理 Activity 或 Fragment,这是 Android 本身的命名约定。

有很多选项可以构建您的应用程序和组织您的文件夹。我不会说有一个圣杯解决方案。所以你必须尝试其中一些,看看最适合你的。

本文的末尾,我展示了使用风味时的文件夹结构选项,如下所示:

Flavoring

但是还有很多其他项目,所以我建议您了解一些 GitHub 项目是如何组织的,一个好的开始方法是查看此存储库中的项目。特别是“开源应用程序”部分。


6
投票

我目前正在开发一个项目,该项目遵循您所描述的方法。 我不知道这是否是更好的结构,但它对我来说真的很好用。

\lib
  \-model
  \-api
  \-bloc
  \-widgets (commom components)
  \-exceptions
  \-config (config classes/files like routes, theme, specific settings for each environment - dev, production, test)
  \-views
    \-login
    \-home
    \-user_profile
    \-...
  \-main.dart

----- 已编辑 -----

在使用 Flutter 工作了近一年之后,我测试了一些不同的结构,其中有一个特别好,并且提供了令人惊叹的组织......

看看slidy,下图代表了它提供的组织类型。更多详细信息请参阅包装说明。

project organization example


0
投票

过去几年我在团队中参与了不同的 Flutter 项目。我得出以下结构的结论。这显然是自以为是的,因为 Flutter 中没有明确的标准。然而,我总是讨厌将逻辑与 UI 定义混合在一起(所有 Flutter 教程都建议这样做)。

到目前为止我得到的最好的结构如下:

  • lib
    (根目录)
    • model
      (独立存在的类和对象)
    • screens
      (应用程序中的不同屏幕,每个屏幕一个文件夹)
    • services
      (API、本机功能等的所有服务)
    • styles
      (样式和主题)
    • utils
      (独立生活的帮手)
    • widgets
      (自定义小部件)
    • commons.dart
      (常规配置、常量等)
    • main.dart
      (嗯,主要的;-))

model
utils
是完全独立的代码片段。放置在这些文件夹中的类或代码经过全面的单元测试,以确保应用程序的核心行为是安全的。

screens
文件夹有点特别。在此文件夹中,每个屏幕都有一个文件夹(如屏幕截图)。对于一个屏幕,我们有一个 UI 文件和一个控制器/状态文件。它允许拆分用户界面和控制 UI 的逻辑。通常:

  • screens
    • main
      • main_controller.dart
      • main_screen.dart
    • game_over
      • game_over_controller.dart
      • game_over_screen.dart

*_controller.dart
文件主要是一个扩展
ChangeNotifier
的类。
*_screen.dart
正在观看
context.watch
(如果需要从控制器更新)或读取
context.read
(如果绘制后不需要更新)。

这是一个基本示例来说明逻辑和 UI 之间的分离:

lib/screens/main/main_screen.dart

class MainScreen extends StatelessWidget {
  const MainScreen({super.key});

  @override
  Widget build(BuildContext context) {
    var appState = context.watch<MainController>();
    var gameStatus = appState.gameStatus;

    Logger logger = Logger("main");
    logger.fine(gameStatus.describe());
    switch (gameStatus) {
      case GameStatus.menu:
        return const Placeholder(color: Colors.green);
      case GameStatus.game:
        return const Placeholder(color: Colors.red);
      case GameStatus.gameOver:
        return const Placeholder(color: Colors.blue);
      default:
        throw StateError("GameStatus ${gameStatus.name} unknown.");
    }
  }
}

lib/screens/main/main_controller.dart

class MainController extends ChangeNotifier {
  var gameStatus = GameStatus.menu;

  void goToGame() {
    gameStatus = GameStatus.game;
    notifyListeners();
  }

  void goToMenu() {
    gameStatus = GameStatus.menu;
    notifyListeners();
  }

  void goToGameOver() {
    gameStatus = GameStatus.gameOver;
    notifyListeners();
  }
}

这种方法允许独立测试控制器的行为。然后,屏幕唯一的责任是显示控制器提供的内容。

© www.soinside.com 2019 - 2024. All rights reserved.