我是使用 flutter 编程的新手,我想开发一个包含几个屏幕的小项目:登录、主页、设置、用户、购买历史记录等。
我需要组织包内的代码,以便于阅读。
如果我开发一个Android应用程序,我会创建一些包:model、activity、fragment、util等。如果我创建一个LoginActivty,我会把它放在activity包中。如果我创建一个用户模型,我会将其放入模型包中。等等。
那么如果我开发一个 flutter 项目,我应该将迄今为止创建的所有文件放在哪里?
目前我只创建了模型包。
我目前正在开发一个项目,该项目遵循您所描述的方法。 我不知道这是否是更好的结构,但它对我来说真的很好用。
\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,下图代表了它提供的组织类型。更多详细信息请参阅包装说明。
过去几年我在团队中参与了不同的 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();
}
}
这种方法允许独立测试控制器的行为。然后,屏幕唯一的责任是显示控制器提供的内容。