Skip to content

Repository files navigation

Flutter Starter App

🚀 Flutter Starter App

✨ 主打分层架构 · MVVM · Clean Architecture 的 Flutter 开箱即用代码模板

Flutter Dart Riverpod License


这是一个面向中大型 Flutter 项目的快速启动模板。项目以 Feature-First 组织业务模块,在每个业务 Feature 内落地 Data / Domain / Presentation 分层,并通过 BasePage + PageLogic + BaseVM / BaseAutoDisposeVM + Riverpod 建立职责清晰的 MVVM 开发范式。

模板已内置多环境、网络请求、路由守卫、主题、国际化、本地存储、登录会话、通用 WebView 页面、Toast/Loading、刷新、按钮、弹窗等常用基础设施。Clone 后只需要替换业务接口与页面,即可进入功能开发。

📘 第一次使用模板请先阅读:模板使用说明。

🧪 测试与质量门禁请查看:测试与质量保障。

🤖 AI 指令统一管理请查看:Ruler AI 指令管理。

📚 目录


✨ 核心优势

能力 说明
清晰分层 每个业务模块按 data / domain / presentation 拆分,职责边界明确
MVVM 开发范式 BasePage 承载页面骨架,PageLogic 承载页面私有生命周期与局部交互,BaseVM / BaseAutoDisposeVM 只承载状态与业务动作
Clean Architecture 业务依赖抽象而非实现,Repository 接口与实现分离,便于替换数据源
Feature-First 业务代码按功能聚合,模块可独立演进,避免按技术层级散落全局
Riverpod 驱动 状态管理、依赖注入、服务组合统一使用 Riverpod,减少框架混用成本
开箱即用基础设施 网络、路由、主题、存储、认证、国际化、异常捕获、日志、组件均已预置
多环境支持 Dev / SIT / Prod 独立入口,环境配置通过 EnvConfig 注入
易扩展 新增 Feature 时复用既有目录、路由、ViewModel、Repository 模式即可

🚀 快速开始

# 安装依赖
flutter pub get

# 运行开发环境
flutter run -t lib/main_dev.dart

# 运行 SIT 环境
flutter run -t lib/main_sit.dart

# 运行生产环境
flutter run -t lib/main_prod.dart

# 默认入口同样指向生产环境
flutter run -t lib/main.dart

首次使用建议先修改各环境入口中的 EnvConfig:

await Application.run(
  envConfig: const EnvConfig(
    envTag: EnvTag.dev,
    baseUrl: 'https://dev.example.com',
    apiPathPrefix: '/api',
  ),
);

📁 项目结构

lib/
├── app/                           # 应用启动、根组件、App 路由装配
│   ├── app.dart                   # MaterialApp.router 根组件
│   ├── application.dart           # Application.run 启动入口
│   ├── host/                      # 启动协调、会话协调、AppHost
│   ├── navigation/                # App 路由图组合、Splash、Root/Shell 导航骨架
│   │   ├── app_router_config.dart # AppRouterConfig 注入
│   │   ├── shell/                 # RootRoute / RootShellRoute / 底部 Tab 容器
│   │   └── splash/                # 启动展示页
├── core/                          # 全局基础设施,不承载具体业务
│   ├── config/                    # EnvConfig / EnvTag / appConfig
│   ├── constant/                  # 常量
│   ├── exception/                 # 全局异常捕获
│   ├── feature/                   # AppFeature 模块协议
│   ├── l10n/                      # 国际化
│   ├── network/                   # 网络、连接状态、HTTP 客户端
│   ├── router/                    # GoRouter 封装、守卫、导航抽象
│   ├── service/                   # 日志等全局基础服务
│   ├── storage/                   # SharedPreferences / SecureStorage 封装
│   ├── theme/                     # 主题、色值、主题资源
│   └── util/                      # 工具类
├── features/                      # 业务功能模块
│   ├── exports.dart               # 业务页面可用的 Route / 公开类型导出
│   ├── features.dart              # App Feature 注册与路由/Tab/Provider 汇聚
│   ├── auth/                      # 登录示例
│   ├── profile/                   # 个人中心与主题/退出登录示例
│   └── todo/                      # 默认根 Tab 与完整分层示例
├── shared/                        # 跨 Feature 共享能力
│   ├── presentation/              # BasePage / PageLogic / BaseVM / BaseAutoDisposeVM / BaseState / PresentationFeedbackService
│   ├── services/                  # AuthSession / AuthStore / AppEventBus
│   ├── widgets/                   # Toast、Loading、Button、Dialog 等组件
│   └── webview/                   # 通用 WebView 页面、配置与公共路由
├── header.dart                    # 业务页面常用导出,app/core/shared 内部不使用
├── main_dev.dart                  # 开发环境入口
├── main_sit.dart                  # SIT 环境入口
├── main_prod.dart                 # 生产环境入口
└── main.dart                      # 默认入口

项目根目录还包含 AI 指令管理源文件:

.ruler/                            # Ruler AI 指令源文件,需纳入版本控制
├── AGENTS.md                      # 项目 AI 指令总入口
├── ruler.toml                     # Ruler 配置
├── architecture.md                # 架构规则
├── flutter_conventions.md         # Flutter / Dart 约定
├── routing.md                     # 路由规则
├── state_management.md            # 状态管理规则
├── testing.md                     # 测试与质量规则
├── documentation.md               # 文档维护规则
└── skills/                        # 可分发给 AI 工具的项目技能

Ruler 生成的 AGENTS.md、CLAUDE.md、.claude/skills/、.cursor/skills/、.codex/ 等文件由 .gitignore 忽略,不应手动修改或提交。详见 Ruler AI 指令管理。

单个 Feature 推荐结构:

lib/features/<feature>/
├── <feature>_feature.dart          # Feature 声明与路由导出
├── data/
│   ├── datasources/               # 远程/本地数据源
│   └── repositories/              # Repository 实现
├── domain/
│   ├── entities/                  # 业务实体
│   ├── exceptions/                # 领域异常
│   └── repositories/              # Repository 抽象
└── presentation/
    ├── pages/                     # 页面
    ├── viewmodels/                # ViewModel
    └── <feature>_routes.dart      # Feature 路由定义

该结构适用于 Todo、订单、登录等有业务状态、Repository 或接口编排的复杂 Feature。需要把 Repository 返回结果写入 App 级状态源时,优先通过 shared/services 中的稳定 Controller 或 Service 编排。纯展示页、设置页、Profile 这类只读取少量全局 Provider 或只有简单点击回调的页面,可以只保留 presentation/pages 与路由文件,不需要为了形式统一创建空 ViewModel、空 State、空 data 或空 domain 目录。


🏗 架构设计

分层关系

┌──────────────────────────────────────────────┐
│                Presentation                  │
│       Page · ViewModel · Route · Widget      │
│             UI 展示、状态管理、交互             │
├──────────────────────────────────────────────┤
│                   Domain                     │
│            Entity · Repository 接口           │
│              业务模型、业务抽象                 │
├──────────────────────────────────────────────┤
│                    Data                      │
│        DataSource · Repository 实现           │
│              接口请求、缓存、数据转换            │
└──────────────────────────────────────────────┘

依赖方向:

Presentation  ──────▶  Domain  ◀──────  Data
     UI                 抽象              实现

这种依赖关系让页面只关心业务抽象,数据来源可以在 API、Mock、本地缓存之间切换,而不会影响 UI 层。

模块职责

模块 职责 依赖规则
app/ 应用启动、环境注入、根组件挂载 可组合全局能力
core/ 网络、路由、存储、主题、DI、异常、工具 不依赖具体 Feature
features/ 业务模块 可依赖 core 与 shared
shared/ BasePage、PageLogic、BaseVM、BaseAutoDisposeVM、PresentationFeedbackService、认证服务、事件总线、通用组件、通用 WebView 等跨 Feature 能力 提供跨业务复用能力,不承载具体业务流程

🧭 MVVM 基础能力

模板通过 BasePage、PageLogic、BaseVM、BaseAutoDisposeVM、BaseState、PresentationFeedbackService 固化页面开发方式,同时保持 Page、PageLogic 与 ViewModel 的职责边界:Page 负责 UI 结构、Widget 组合、布局、样式;PageLogic 负责页面本地 controller、临时交互状态、生命周期、调用 VM/Provider;ViewModel / Notifier 负责页面可观察状态、业务动作编排,并把领域/服务状态转换成 UI 状态。

BasePage

BasePage 是纯页面壳,不绑定具体 ViewModel,负责 UI 结构、Widget 组合、布局和样式:

  • 标准 Scaffold 构建
  • AppBar、背景色、SafeArea、KeepAlive 扩展点
  • 背景点击自动收起键盘
  • App 生命周期监听与 PageLogic 生命周期分发:onInit / onReady / onResume / onPause / onDispose
  • Pop 拦截与默认返回能力
  • 通过 PageScope 向子类提供 context、ref 与可选 PageLogic

PageLogic 是按需使用的页面本地逻辑层,用于承载只属于当前页面的 controller、FocusNode、临时交互状态、生命周期、首帧副作用,以及页面级导航/弹窗编排,不放跨页面业务状态。页面如需使用,覆盖 createPageLogic() 并通过 scope.logic<XxxPageLogic>() 取得实例:

final class OrderPageLogic extends PageLogic {
  @override
  void onReady() {
    unawaited(loadOrders());
  }

  Future<void> loadOrders() {
    return presentation.runWithLoading(
      () => ref.read(orderViewModelProvider.notifier).loadOrders(),
      rethrowError: false,
    );
  }
}

推荐使用 PageLogic 的场景:

  • 页面持有 TextEditingController、FocusNode、ScrollController 或动画控制器。
  • 页面需要 onReady、onResume、onPause、首帧加载或可见性相关副作用。
  • 页面存在不适合进入 ViewModel 的临时 UI 状态。
  • 页面需要编排登录后跳转、确认弹窗、输入框提交等 UI 副作用。

可以不使用 PageLogic 的场景:

  • 纯展示页面。
  • 只通过 ref.watch 渲染 Provider 状态的简单页面。
  • 只有少量点击回调,且不需要 controller、生命周期或页面私有状态。

PageLogic 可以调用 VM/Provider,但不要承载可观察业务状态、接口编排、跨页面状态或领域逻辑;这些职责应放入 ViewModel、Service、Repository 或稳定 Provider。

页面在 page(scope) 中按需桥接状态与 PageLogic:

@override
Widget page(PageScope scope) {
  final logic = scope.logic<OrderPageLogic>();
  final state = scope.ref.watch(todoViewModelProvider);

  return TodoContent(state: state, onRefresh: logic.loadOrders);
}

BaseVM / BaseAutoDisposeVM

BaseVM 与 BaseAutoDisposeVM 分别基于 Riverpod Notifier 与 AutoDisposeNotifier,只用于承载页面可观察状态、业务动作编排,并把领域/服务状态转换成 UI 状态:

  • initialState() 提供初始状态
  • 通过 state = state.copyWith(...) 更新 UI 状态
  • 调用 Repository 抽象完成业务数据读写
  • 不感知 BuildContext、Widget 生命周期、页面返回、页面 ready 策略或一次性 UI 反馈服务

选择基类时按状态保留需求区分:需要跨页面或离开页面后继续保留状态时使用 BaseVM 并配套 NotifierProvider;只服务当前页面、最后一个监听者移除后即可释放状态时使用 BaseAutoDisposeVM 并配套 AutoDisposeNotifierProvider。

BaseState

BaseState 是纯状态基类,不内置页面级字段。业务页面如需首屏加载、空态、错误态,应在各自 Feature 的 State 中显式建模,例如 initialized、loading、errorMessage。

PresentationFeedbackService

PresentationFeedbackService 承接 Presentation 层的一次性 UI 反馈,并通过 presentationFeedbackProvider 注入:

  • runWithLoading 包装异步任务
  • emitHint 展示提示
  • showLoading / hideLoading 控制全局 Loading

这些反馈不进入 BaseState,避免临时事件污染可渲染状态。BasePage / PageLogic 可通过 scope.presentation 或 presentation 访问;BaseVM / BaseAutoDisposeVM 不直接持有 Presentation 反馈服务。Loading 使用 token/counter 管理,并发 action 不会被静默跳过;runWithLoading 默认展示错误提示后继续抛出异常,需要吞掉异常时必须显式传入 rethrowError: false。

推荐页面开发流程:

Page 负责 UI 结构、Widget 组合、布局、样式
  ↓ 用户交互
PageLogic 负责页面本地 controller、临时交互状态、生命周期、调用 VM/Provider
  ↓ 调用动作
ViewModel / Notifier 负责可观察状态、业务动作编排、领域状态到 UI 状态的转换
  ↓ 调用抽象
Repository 负责业务数据获取
  ↓ 委托实现
DataSource / HttpClient 负责具体数据来源

📦 核心模块

🧩 启动引导与依赖注入

应用统一从 Application.run() 启动,启动前初始化集中在 Application.bootstrap() 中,启动后的首跳由 AppHost 协调:

main()
  → Application.run(envConfig)
      → WidgetsFlutterBinding.ensureInitialized()
      → 初始化普通存储与安全存储
      → 恢复 AuthSession 到 authSessionProvider
      → appFeatureProviderOverrides 注入 Feature 默认 data 实现
      → createAppRouterOverrides() 注入 AppRouterConfig
  → AppExceptionCatcher.runAppGuarded()
  → ProviderScope(overrides: overrides)
  → MaterialApp.router
  → AppHost 在 Splash 后根据登录态跳转 RootRoute 或 LoginRoute

这样可以保证存储、登录会话、环境配置在应用挂载前完成初始化,同时把启动页停留与登录态首跳从业务 Feature 中解耦出来。

🌍 多环境配置

环境 入口 适用场景
Dev lib/main_dev.dart 本地开发、调试、抓包
SIT lib/main_sit.dart 测试环境、联调环境
Prod lib/main_prod.dart 生产环境

EnvConfig 支持配置:

  • baseUrl、apiPathPrefix
  • 日志开关
  • 代理/抓包配置
  • 重试策略
  • 证书校验策略
  • 隐私协议、用户协议地址

🌐 网络层

网络层基于 Dio 封装,业务侧依赖统一的 HTTP 抽象,不直接散落 Dio 调用。

HttpConfig
  ↓
httpClientProvider
  ↓
BaseHttpClient / DioHttpClient
  ↓
Interceptor Chain + Cache + Retry + Mock + Batch Request

已内置能力:

  • Token 自动注入
  • 业务状态码解析
  • 异常捕获与分类
  • 日志输出
  • 抓包代理支持
  • 请求缓存策略
  • 指数退避重试
  • Mock 支持
  • 批量请求封装

缓存策略包括:

noCache · cacheFirst · networkFirst · cacheOnly · networkOnly · staleWhileRevalidate

🧭 路由系统

路由基于 GoRouter,但 Presentation/Page 层通过模板封装的路由定义与导航抽象使用,减少对第三方路由库的直接依赖。

Feature Route Node → AppPageRoute / AppShellRoute  → GoRoute / StatefulShellRoute
Feature Module     → AppFeature / AppTabEntry      → AppFeatureRegistry
Feature DI         → providerOverrides             → domain binding Provider
App Composition    → AppRouterConfig               → goRouterProvider
Page Navigation    → BaseNavigator                 → RouterNavigator

特点:

  • 每个 Feature 自己维护路由定义
  • 每个 Feature 通过 XxxFeature 暴露元数据、模块路由、可选底部 Tab 入口与默认 Provider 装配
  • features/features.dart 保留候选列表,并按当前环境创建唯一的 AppFeatureRegistry
  • 注册表按 priority 升序、Feature key 升序稳定排序,并校验 Feature key、route path 与 Tab key 唯一
  • features/exports.dart 只导出业务页面需要的 route class 与公开类型,并由 header.dart 汇总
  • lib/app/navigation/app_router_config.dart 组合 Splash、Root/Shell、Feature 路由与 App 公共路由,并注入 core/router
  • header.dart 只作为业务页面便捷入口,App/Core/Shared 内部使用精确 import,避免隐式依赖 Feature
  • App Shell 从当前环境注册表的 tabs 自动装配底部 Tab 分支;无 Tab 时不创建 Root redirect / Shell
  • 支持公开路由与登录态路由
  • 未登录访问受保护页面时自动跳转登录页
  • 提供 root navigator key,支持非 UI 场景导航

🔐 登录会话

模板内置通用登录会话模型与安全存储:

AuthSession
  ↓
AuthSessionController
  ↓
authSessionProvider
  ↓
Router Guard / AuthInterceptor / UI

AuthSession 以 token、refreshToken 与可扩展 payload 为核心,适配不同后端登录协议。authSessionProvider 是 App 内唯一响应式登录态状态源,负责守卫判断、HTTP token 注入与 UI 订阅;AuthSessionController 是语义化写入口,统一保存、清空和更新会话;AuthStore 只作为其安全存储后端。登录 Feature 中提供了完整示例:页面表单、ViewModel、Repository、DataSource、会话落盘与退出登录,其中 AuthRepositoryImpl 只返回 AuthSession,不直接写全局会话。

🌐 通用 WebView 页面

模板内置 webview_flutter 驱动的通用网页容器,位于 lib/shared/webview/,适合隐私政策、用户协议、帮助中心和业务 H5。它不作为业务 Feature 注册,公共路由由 App 路由组合层统一加入路由图。

快速打开公开网页:

ref.read(appRouterProvider).push(
  const WebPageRoute(
    url: 'https://example.com/privacy',
    title: '隐私政策',
  ).location,
);

需要登录的业务 H5 使用 AuthWebPageRoute:

ref.read(appRouterProvider).push(
  const AuthWebPageRoute(url: 'https://example.com/member').location,
);

需要 headers、白名单或 WebView 行为开关时,通过 extra 传入 WebPageConfig:

ref.read(appRouterProvider).push(
  const AuthWebPageRoute().location,
  extra: const WebPageConfig(
    url: 'https://example.com/member',
    allowedHosts: ['example.com'],
    headers: {'X-Source': 'app'},
  ),
);

未传 allowedHosts 时允许任意 http/https;传入后仅允许白名单 host。非 http/https 地址会被拦截,不会尝试外部 App 唤起。

🎨 主题与资源

主题系统支持亮/暗模式,并通过 Riverpod 持久化主题选择。

能力包括:

  • Material 3 主题配置
  • ThemeExtension 扩展语义化色值
  • 亮/暗主题资产切换
  • BuildContext 扩展访问颜色与资源
  • assets/images/ 与 assets/images/dark/ 分离

示例:

context.appColor.brand
context.appAsset.logo

🌏 国际化

国际化使用 Flutter 官方 gen-l10n:

  • 源文件:lib/core/l10n/arb/app_en.arb
  • 源文件:lib/core/l10n/arb/app_zh.arb
  • 配置文件:l10n.yaml
  • 生成脚本:./script/gen_l10n.sh

切换语言示例:

ref.read(appLocaleProvider.notifier).setLocale(AppLocale.zh);

💾 存储层

模板将普通数据与敏感数据分开处理:

实现 底层 场景
PrefsStorage SharedPreferences 主题、语言、普通偏好
SecureStorage FlutterSecureStorage Token、登录态、敏感凭证

业务代码通过统一抽象访问存储,便于测试和替换实现。

🧱 通用组件

shared/widgets 已内置常用组件:

组件 用途
Toast / Loading 全局轻提示、加载态
Dialog / Sheet 通用弹窗、确认面板、选择面板与业务选择面板
RefreshView 下拉刷新、上拉加载
PrimaryRoundButton 主按钮
CountdownRoundButton 验证码倒计时按钮
InputTextWidget 输入框
ImageView 本地、网络、SVG、Base64 图片展示
SwitchWidget 开关组件
BaseCard 基础卡片容器
LabelRow 标签行、箭头行、开关行
ContextMenu / Overlay 浮层与菜单能力

🛠 开发指南

➕ 添加一个新 Feature

  1. 在 lib/features/ 下创建模块目录。
  2. 按 data / domain / presentation 创建分层文件。
  3. 在 domain/repositories 中定义 Repository 抽象。
  4. 在 domain/repositories 中定义 Repository 抽象 Provider,在 data/repositories 中实现 Repository。
  5. 如页面存在可观察业务状态或动作编排,在 presentation/viewmodels 中按状态保留需求继承 BaseVM 或 BaseAutoDisposeVM 管理 UI 状态与业务动作。
  6. 在 presentation/pages 中继承 BasePage 编写 UI,并在 page(scope) 中读取状态、调用 ViewModel 或稳定 Provider。
  7. 在 <feature>_routes.dart 中声明路由。
  8. 在 <feature>_feature.dart 中继承 AppFeature,声明唯一 key、priority、允许环境等元数据并暴露路由;如有默认 data 实现,在 providerOverrides 中装配 domain binding Provider。
  9. 在 features/features.dart 中注册 XxxFeature();App 路由配置与根 ProviderScope 会自动消费 appFeatures。
  10. 如 route class 或公开类型需要给业务页面使用,在 features/exports.dart 中导出。

ViewModel 只依赖 domain 抽象 Provider,不直接 import data/repositories 或 data/datasources。

AppFeatureMetadata.permissions 只声明业务权限 key,不执行鉴权;experimental 只标记实验模块。默认启用全部环境、无权限且非实验功能。注册表发现 Feature key、route path、Tab key 冲突或 Tab 引用了所属 Feature 未声明的路由时会立即失败。

推荐最小结构:

lib/features/order/
├── order_feature.dart
├── data/
│   ├── datasources/order_datasource.dart
│   └── repositories/order_repository_impl.dart
├── domain/
│   ├── entities/order.dart
│   ├── exceptions/order_exception.dart
│   └── repositories/order_repository.dart
└── presentation/
    ├── order_routes.dart
    ├── pages/order_page.dart
    └── viewmodels/order_viewmodel.dart

如果只是简单页面,可以使用更薄的结构:

lib/features/profile/
├── profile_feature.dart
└── presentation/
    ├── pages/profile_page.dart
    └── profile_routes.dart

📝 页面开发建议

  • UI 逻辑放在 Page,业务动作放在 ViewModel。
  • ViewModel 通过 Repository 抽象获取数据。
  • 简单页面不要机械创建空 ViewModel、空 State 或空分层目录。
  • 不在 Page 中直接调用 Dio、SharedPreferences、SecureStorage。
  • 不让 Feature 直接依赖其他 Feature 的内部实现。
  • 可复用 UI 放到 shared/widgets,可复用业务服务放到 shared/services。

🔌 替换为真实接口

  1. 修改对应环境入口的 baseUrl 与 apiPathPrefix。
  2. 在 Feature 的 DataSource 中替换接口路径。
  3. 在 RepositoryImpl 中完成响应数据到业务实体的转换。
  4. 在 ViewModel 中调用 Repository 并更新状态。

🤖 维护 AI 指令

本项目使用 Ruler 统一管理 Copilot、Cursor、Claude Code、Codex 等 AI Coding Assistant 指令。

  • 指令源文件统一维护在 .ruler/。
  • 不手动修改 Ruler 生成的 AGENTS.md、CLAUDE.md、.claude/skills/、.cursor/skills/、.codex/ 等文件。
  • 修改 .ruler/ 后,先运行 ruler apply --dry-run --verbose 预览,再运行 ruler apply。
  • 提交时包含 .ruler/ 与 .gitignore 的变更,不提交生成文件。

详细说明见:Ruler AI 指令管理。


🔧 脚本工具

脚本 用途
./script/gen_l10n.sh 生成国际化代码
./script/gen_app_icon.sh 根据 assets/app_icon.png 生成 App 图标
./script/build_android.sh [apk|aab] 构建 Android release 包,并收集混淆符号与 R8 mapping
./script/build_ios.sh 构建 iOS release IPA,并收集混淆符号与 dSYM
dart run script/rename_project.dart <name> --package-id <id> --app-name <name> --en-app-name <name> 重命名项目
# 生成国际化代码
./script/gen_l10n.sh

# 生成 App 图标
./script/gen_app_icon.sh

# 构建 Android APK,默认输出 apk
./script/build_android.sh

# 构建 Android AAB
./script/build_android.sh aab

# 构建 iOS IPA
./script/build_ios.sh

# 构建脚本会执行 flutter pub get,并使用 release + obfuscate + split-debug-info
# Android 产物归档到 app_release_packages/android/<version>/
# iOS 产物归档到 app_release_packages/ios/<version>/
# Dart 混淆符号表保存在对应归档目录的 symbols/ 子目录
# Android 会额外收集 mapping.txt 与 native-debug-symbols.zip(如存在)
# iOS 会额外收集 dSYMs,并在缺少 objective_c.framework.dSYM 时尝试用 dsymutil 补齐

# 重命名项目
dart run script/rename_project.dart my_app \
  --package-id com.example.myapp \
  --app-name "我的APP" \
  --en-app-name "My App"

# 脚本会同步更新 Android、iOS、macOS、Linux、Web、Windows 的应用名、包名/Bundle ID 与启动配置
# 不会直接修改国际化生成物,也不会猜测公司名、版权、签名等发布主体信息

# 重命名后重新生成国际化代码
./script/gen_l10n.sh

📚 主要依赖

类型 依赖
状态管理 / DI flutter_riverpod
路由 go_router
网络 dio、connectivity_plus
存储 shared_preferences、flutter_secure_storage
国际化 flutter_localizations、intl
UI / 体验 bot_toast、easy_refresh、flutter_screenutil、cached_network_image、loading_animation_widget、shimmer、flutter_svg
工程能力 exception_catcher、logger、package_info_plus、permission_handler、flutter_launcher_icons

MIT License · 可自由用于个人与商业项目

About

Flutter Starter with MVVM, Clean Architecture, Riverpod, GoRouter, Dio, Multi-Environment Setup, Theming, Localization, and Reusable Enterprise Modules.

Topics

Resources

Stars

17 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages