前言
当前案例 Flutter SDK版本:3.22.2
-
目前Flutter项目,很多都是在一个目录中,导致文件繁多,不利于维护,于是我尝试,创建不同目录进行模块开发,结果成功了,在此分享一下;
-
项目中加入了一些常用操作
provider
: 状态管理;fluro
: 路由管理;- 跨模块,读取静态资源:字体、图片;
效果图
结构图
方式一
1、创建根目录
新建一个空文件夹;
2、创建模块
在 flutter_module_develop
文件夹中,创建Flutter项目;
2.1、创建主模块
注意是Application
类型,命名为app,这个命名大家随意;
2.2、创建子模块
注意是Package
类型,common、home、order、personal;
3、建立依赖关系
- 修改各个模块的
pubspec.yaml
文件,建立依赖关系; - 没有出现 循环依赖 的问题;
3.1、Common
name: common
description: "A new Flutter project."
publish_to: none
version: 0.0.1
homepage:
environment:
sdk: '>=3.4.3 <4.0.0'
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
app:
path: ../app
home:
path: ../home
order:
path: ../order
personal:
path: ../personal
provider: ^6.1.2
fluro: ^2.0.5
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.0
flutter:
assets:
- assets/images/
fonts:
- family: Basteleur
fonts:
- asset: assets/fonts/Basteleur.ttf
3.2、Home
name: home
description: "A new Flutter project."
publish_to: none
version: 0.0.1
homepage:
environment:
sdk: '>=3.4.3 <4.0.0'
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
common:
path: ../common
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.0
flutter:
# To add assets to your package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
3.3、Order
name: order
description: "A new Flutter project."
publish_to: none
version: 0.0.1
homepage:
environment:
sdk: '>=3.4.3 <4.0.0'
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
common:
path: ../common
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.0
flutter:
# To add assets to your package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
3.4、Personal
name: personal
description: "A new Flutter project."
publish_to: none
version: 0.0.1
homepage:
environment:
sdk: '>=3.4.3 <4.0.0'
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
common:
path: ../common
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.0
flutter:
# To add assets to your package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
3.5、App
name: app
description: "A new Flutter project."
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: '>=3.4.3 <4.0.0'
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.6
common:
path: ../common
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.0
flutter:
uses-material-design: true
路由配置
routers.dart
;
import 'package:app/page/main_index.dart';
import 'package:common/page/common_index.dart';
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:home/page/home_index.dart';
import 'package:order/page/order_index.dart';
import 'package:personal/page/personal_index.dart';
class App {
static const String root = '/';
}
class Common {
static const String commonIndex = '/CommonIndex';
}
class Home {
static const String homeIndex = '/HomeIndex';
}
class Order {
static const String orderIndex = '/OrderIndex';
}
class Personal {
static const String personalIndex = '/PersonalIndex';
}
class Routers {
static FluroRouter router = FluroRouter();
// 配置路由
static void configureRouters() {
router.notFoundHandler = Handler(handlerFunc: (_, __) {
// 找不到路由时,返回指定提示页面
return const Scaffold(
body: Center(
child: Icon(Icons.error),
),
);
});
// 初始化路由
_initRouter();
}
// 注册路由
static _initRouter() {
_initCommonIndex();
_initOrderIndex();
_initPersonalIndex();
_initHomeIndex();
_initRootIndex();
}
// 根页面
static void _initRootIndex() {
router.define(
App.root,
handler: Handler(
handlerFunc: (_, __) => const MainIndex(),
),
);
}
// 首页
static void _initHomeIndex() {
router.define(
Home.homeIndex,
handler: Handler(
handlerFunc: (_, __) => const HomeIndex(),
),
);
}
// 个人页面
static void _initPersonalIndex() {
router.define(
Personal.personalIndex,
handler: Handler(
handlerFunc: (_, __) => const PersonalIndex(),
),
);
}
// 订单页面
static void _initOrderIndex() {
router.define(
Order.orderIndex,
handler: Handler(
handlerFunc: (_, __) => const OrderIndex(),
),
);
}
// 公共页面
static void _initCommonIndex() {
router.define(
Common.commonIndex,
handler: Handler(
handlerFunc: (_, __) => const CommonIndex(),
),
);
}
}
navigator_util.dart
;
import 'package:common/router/routers.dart';
import 'package:fluro/fluro.dart';
import 'package:flutter/cupertino.dart';
/// 路由工具类
/// 如果所在类没有 context,可以使用 全局context:navigatorKey.currentContext
class NavigatorUtil {
/// 前往页面
static Future<dynamic> push(
BuildContext context,
path, {
bool replace = false, // 替换,进入新的页面时,将当前页面销毁
bool clearStack = false, // 清空路由栈,进入新的页面时,其他实例的页面全部销毁
Object? arguments, // 传递的参数
TransitionType? transition, // 页面跳转的动画 类型
}) {
return Routers.router.navigateTo(
context,
path,
replace: replace,
clearStack: clearStack,
transition: transition ?? TransitionType.inFromRight, // 默认跳转动画,从右侧进入
routeSettings: RouteSettings(
arguments: arguments,
),
);
}
}
Provider
import 'package:flutter/material.dart';
class Counter extends ChangeNotifier {
int count = 0;
void compute() {
count++;
notifyListeners();
}
}
// 使用
Consumer<Counter>(
builder: (_,state,__) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('${state.count}'),
IconButton(onPressed: () {
state.compute();
}, icon: const Icon(Icons.add)),
],
);
}
),
静态资源访问
-
跨模块访问静态资源:要设置
package
属性;- package 属性的作用: 指定资源来自某个特定的包,最终访问的路径是 packages/<package_name>/<resource_path>。
- 比如当前图片,放在 common 模块,引用的时候,package属性的值就写 common;
- Image.asset('assets/imgs/logo.png',package: 'common');
- 最终访问的资源路径是:packages/common/assets/imgs/logo.png
-
以下是支持
package
属性的主要组件或配置:
类别 | 组件/配置 | 是否支持 package 属性 |
---|---|---|
图片加载 | Image.asset | ✅ |
图片加载 | AssetImage | ✅ |
字体加载 | TextStyle | ✅ |
字体加载 | RichText | ✅ |
主题配置 | ThemeData | ✅ |
自定义资源加载 | DefaultAssetBundle | ✅ |
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
fontFamily: 'Basteleur',
package: PACKAGE_COMMON_NAME,
),
);
}
源码地址
https://github.com/youxia-mrhan/flutter_module_develop
方式二(模块独立启动)
-
方式一 是以 app 主模块 为
Application
类型,子模块为Package
类型,满足绝大多数场景,但子模块 不能独立运行。 -
和方式一的区别:子模块 全部选择为
Application
类型,common、home、order、personal,实现 模块独立启动
源码地址
https://github.com/youxia-mrhan/flutter_module_develop2
注意事项
- 当IDE找不到依赖包路径时,需要手动导包;
- 比如IDE无法自动导入 import 'package:app/main/app.dart,那就手写;
- 当一个模块发生了改变,比如 增删 操作,使用它的其他模块,必须 重新 pub get 同步一下,否则其他模块,使用的还是这个模块 之前的缓存;
打包体积
- 两种方式的打包体积,是相同的;
cd app
flutter build apk
✓ Built build/app/outputs/flutter-apk/app-release.apk (18.9MB)
开发IDE推荐
-
开发Flutter,用的比较多的IDE工具有:
Android Studio
、Visual Studio Scode
、Intellij IDEA
等;
-
推荐
Visual Studio Scode
,这种分模块开发,会导致一些的IDE,无法进行断点调试,但Visual Studio Scode
可以,它可以将多个目录,整合到一个工作区,非常强大;- 使用
Visual Studio Scode
直接打开 根目录flutter_module_develop
; - 配置启动文件
launch.json
;
- 使用