GeniusArchitecture

这是使用 Provider、Firebase、Dio 和 Robert C Martin 清洁架构的一些基本原理创建的 Flutter 样板项目。

入门

该样板是一个最小化的实现,可用于创建新项目或库。它带有一系列基本组件,例如应用程序架构、主题和必要的依赖项。该存储库代码可用作初始化程序,以快速构建新项目并缩短开发时间。

如何使用

步骤 1

使用下面的链接下载或克隆此仓库

https://github.com/GeniusCrew-B-V/genius-architecture-boilerplate.git  

步骤 2

转到项目根目录,在控制台中执行以下命令以获取所需的依赖项

flutter pub get   

步骤 3:通过项目范围的搜索并用您想要的名称替换“com.baseprojectsrl.baseproject”来更改包名

步骤 4

此项目使用代码生成来生成域/网络模型和应用程序本地化,请执行以下命令来生成文件

flutter packages pub run build_runner build --delete-conflicting-outputs  

或使用 watch 命令以自动同步源代码

flutter packages pub run build_runner watch  

步骤 5

前往 Firebase,创建一个新项目,进行配置,并将 GoogleServices-Info.plist 和 google-services.json 放在正确的位置,如果您跳过此步骤,应用程序将无法运行

隐藏生成的文件

为了隐藏生成的文件,请导航到 `Android Studio` -> `Preferences` -> `Editor` -> `File Types` 并在 `ignore files and folders` 部分粘贴以下行

*.inject.summary;*.inject.dart;*.g.dart;  

在 Visual Studio Code 中,导航到 `Preferences` -> `Settings` 并搜索 `Files:Exclude`。添加以下模式

**/*.inject.summary  
**/*.inject.dart  
**/*.g.dart  

样板项目功能

  • 启动屏
  • 惰性加载列表
  • 登录
  • 首页
  • 路由
  • 主题
  • Dio
  • 数据库
  • Provider (状态管理)
  • 验证
  • 代码生成
  • 依赖注入
  • 深色主题支持
  • 多语言支持

文件夹结构

这是我们在此项目中使用的文件夹结构

lib/  
|- dev/  
   |- main.dart  
|- i18n/  
|- prod/  
   |- main.dart  
|- resources/  
|- src/  
   |- base  
   |- home_page  
   |- login  
   |- post_detail  
   |- profile_page  
   |- signup  
   |- start  
   |- updates  
   |- app.dart  

现在,让我们深入 `lib` 文件夹,其中包含应用程序的主要代码。

1- dev - This is where the starting point of the application in case we want to work in a hipotetycal   
       development enviroment  
2- i18n - Here we have all the .yaml files for each localization that we would need  
3- prod - This is where the starting point of the application in case we want to work in a hipotetycal   
        production enviroment  
4- resources - Here we have all the possible resources needed (Sizes,Image references etc.)  
5- src - This is where we develop the app itself  
   1- base - Base feature is where we manage the whole app which isn't specifically feature-related, and   
           instead it's app related. It contains all the non-feature releated data  
   2- home_page - Home page feature  
   3- login - Login page feature  
   4- post_detail - Post detail page feature  
   5- profile_page - Profile page  feature  
   6- signup - Signup page feature  
   7- start - Start feature is the first feature always launcher, it cointains basic navigation and auth   
            capabilities  
   8- updates- Updates page feature  
   9- app.dart - This is the real starting point of the application, where we inject all the  
              dependencies and run the app  
  

功能结构

每个功能都遵循清洁架构路径的主要原则。

feature/  
|- data  
|- di  
|- domain  
|- ui  

数据层

数据层包含数据源代码,例如 REST API、本地/远程数据库访问或任何其他数据源。在这里,我们遵循一个抽象类的系统,以便遵循域层中定义的方法签名。这会使事情稍微复杂化,但允许我们拥有健壮的代码,并且也有助于测试/调试阶段。

data/  
|- source/  
   |- feature_remote_data_source.dart  
   |- feature_remote_data_source_impl.dart  
|- feature_repository_impl.dart  

依赖注入 (DI)

这是我们让一个类独立于其自身依赖项的地方。这将使我们能够以更易于管理的方式分离应用程序的不同部分,因为每个类可以在任何给定时间调用它所需的任何依赖项。

di/  
|- feature_providers.dart  

领域层

Domain 文件夹包含用于绘制和组织我们数据以及数据层中实现函数的签名的模型。这基本上使域层成为数据层和 UI/逻辑之间的“粘合剂”。

di/  
|- model/  
   |- request_model.dart  
   |- response_model.dart  
|- feature_repository.dart  

UI

在 UI 文件夹中,我们管理页面/导航/小部件/状态管理(ViewModel)。

  • Pages 由我们正在处理的功能中包含的页面组成。它由该功能相关的较小小部件构建而成。

  • Navigator 是我们在该功能内添加导航逻辑的地方,它允许我们在页面之间移动。

  • ViewModel 是我们管理这些页面和整个功能的状态以及业务逻辑的地方。

ui/  
|- model  
|- navigator  
|- pages  
|- viewmodel  
|- widget  

App.dart

这是应用程序的起点。所有应用程序级别的配置均在此文件中定义,例如主题、标题、方向等。可以通过使用 AppConfig 类来配置应用程序的行为,例如风味、端点等。在这种情况下,我们使用 dev/main.dart 和 prod/main.dart 来处理这些事情。

dev/main.dart

import 'package:flutter/material.dart';    
import '../src/app.dart';    
    
void main() {    
 WidgetsFlutterBinding.ensureInitialized();    
  mainCommon(    
     host: "https://31cae3b4-9771-4151-bdb2-41437d3b17ec.mock.pstmn.io",    
     isProd: false,  
  );    
}  

app.dart

import 'dart:io';    
    
import 'package:firebase_core/firebase_core.dart';    
import 'package:firebase_crashlytics/firebase_crashlytics.dart';    
import 'package:flutter/cupertino.dart';    
import 'package:flutter/foundation.dart';    
import 'package:flutter/material.dart';    
import 'package:flutter/services.dart';    
import 'package:flutter_displaymode/flutter_displaymode.dart';    
import 'package:flutter_localizations/flutter_localizations.dart';    
import 'package:provider/provider.dart';    
import 'package:shared_preferences/shared_preferences.dart';    
    
import '../resources/app_config.dart';    
import 'base/settings/di/theme_providers.dart';    
import 'base/settings/ui/viewmodel/theme_viewmodel.dart';    
import 'base/token/di/token_providers.dart';    
import 'base/widget/ui/custom_circular_progress_indicator.dart';    
import 'start/di/start_page_providers.dart';    
import 'start/ui/navigator/start_page_navigator.dart';    
    
void mainCommon({required String host, required bool isProd, required String onesignalAppID}) async {    
 await WidgetsFlutterBinding.ensureInitialized();    
  await Firebase.initializeApp();    
  if(Platform.isAndroid) {    
 await FlutterDisplayMode.setHighRefreshRate();    
  }    
  final prefs = await SharedPreferences.getInstance();    
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]).then(    
 (value) => runApp(    
        MultiProvider(    
           providers: themePageProviders(prefs),    
           builder: (context, __) {    
              final themeViewModel = context.watch<ThemeViewModel>();    
              return App(    
                 host: host,    
                 isProd: isProd,    
                 themeViewModel: themeViewModel,    
              );    
           },     
       ),    
    ),    
  );    
}  

       

GeniusCrew B.V

Van Coothplein 53

4811 ND, Breda

荷兰

GitHub

查看 Github