一、前言
首先先看一下flutter自带的目录
文件或目录 | 说明 |
---|---|
.dart_tool | 记录了一些dart工具库所在的位置和信息 |
.idea | android studio 是基于idea开发的,.idea 记录了项目的一些文件的变更记录 |
android | Android项目文件夹 |
ios | iOS项目文件夹 |
lib | lib文件夹内存放我们的dart语言代码 |
test | 用于存放我们的测试代码 |
.gitignore | git忽略配置文件 |
.metadata | IDE 用来记录某个 Flutter 项目属性的的隐藏文件 |
.packages | pub 工具需要使用的,包含 package 依赖的 yaml 格式的文件 |
flutter_app.iml | 工程文件的本地路径配置 |
pubspec.lock | 当前项目依赖所生成的文件 |
pubspec.yaml | 当前项目的一些配置文件,包括依赖的第三方库、图片资源文件等 |
README.md | READEME文件 |
这就是flutter自带的目录,大概接触过的都懂。但是,在开发中如何编写目录更为重要,也就是lib
内如何将代码分配及编写。一个良好的目录结构能让人快速上手,也能让开发人员快速对过往代码进行优化。接下来就是我习惯性的代码结构。
二、开发目录结构
1 data
这里面包含实体类、网络请求及相关方法或结构
文件或目录 | 说明 |
---|---|
model | 实体类数据结构,toJson或fromJson |
api | 网络请求,eg. dio请求封装 |
services | 网络请求结构封装,eg. dio请求封装 |
(1) model
以下以一个用户的实体类来举例(空安全)
class UserInfo {
int? id;
String? img;
String? thumbimg;
String? userName;
String? intro;
UserInfo({this.id, this.img, this.thumbimg, this.userName, this.intro});
UserInfo.fromJson(Map<String, dynamic> json) {
memberId = json['id'];
img = json['img'];
thumbimg = json['thumbimg'];
userName = json['userName'];
intro = json['intro'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['img'] = this.img;
data['thumbimg'] = this.thumbimg;
data['userName'] = this.userName;
data['intro'] = this.intro;
return data;
}
}
之前同事找到了一个快速生成实体类的网站,是个很不错的网站:JsonToDart
(2) api
主要为网络请求封装,以下为实例
static Future<Map<dynamic, dynamic>> testApi(args, er) async {
var response = await HttpUtil().post(
'/testApi',
{
"args": args,
"er": er
}
);
return response;
}
(3) services
封装网络请求及相关组件
class HttpUtil {
Dio? dio;
static HttpUtil _instance = HttpUtil._internal();
factory HttpUtil() => _instance;
HttpUtil._internal() {
// BaseOptions、Options、RequestOptions 都可以配置参数,优先级别依次递增,且可以根据优先级别覆盖参数
BaseOptions options = new BaseOptions(
// 请求基地址,可以包含子路径
baseUrl: baseUrl,
// baseUrl: storage.read(key: STORAGE_KEY_APIURL) ?? SERVICE_API_BASEURL,
//连接服务器超时时间,单位是毫秒.
connectTimeout: 10000,
// 响应流上前后两次接受到数据的间隔,单位为毫秒。
receiveTimeout: 5000,
// Http请求头.
headers: {
HttpHeaders.acceptHeader:"accept: multipart/form-data"
},
/// 请求的Content-Type,默认值是"application/json; charset=utf-8".
/// 如果您想以"application/x-www-form-urlencoded"格式编码请求数据,
/// 可以设置此选项为 `Headers.formUrlEncodedContentType`, 这样[Dio]
/// 就会自动编码请求体.
contentType: 'application/json; charset=utf-8',
/// [responseType] 表示期望以那种格式(方式)接受响应数据。
/// 目前 [ResponseType] 接受三种类型 `JSON`, `STREAM`, `PLAIN`.
///
/// 默认值是 `JSON`, 当响应头中content-type为"application/json"时,dio 会自动将响应内容转化为json对象。
/// 如果想以二进制方式接受响应数据,如下载一个二进制文件,那么可以使用 `STREAM`.
///
/// 如果想以文本(字符串)格式接收响应数据,请使用 `PLAIN`.
responseType: ResponseType.json,
);
dio = new Dio(options);
// Cookie管理
// CookieJar cookieJar = CookieJar();
// dio.interceptors.add(CookieManager(cookieJar));
}
/// restful get 操作
Future get(
String path,
{
Options? options,
}) async {
var response = await dio!.post(
path,
options: options,
);
return response.data;
}
/// restful post 操作
Future post(
String path,
dynamic data,
{
Options? options,
}) async {
var response = await dio!.post(
path,
queryParameters: data,
options: options,
);
return response.data;
}
}
2 utils
主要为封装的方法或组件
文件或目录 | 说明 |
---|---|
method | 例如加密策略、计算缓存大小、获取手机和应用信息等方法 |
widget | 例如封装Text组件、toast信息、获取头部安全距离等组件 |
3 theme
软件相关的方法或组件
文件或目录 | 说明 |
---|---|
utils | 例如通用依赖包引用、自适应适配宽高单元、多语言等 |
values | 例如通用色值、静态资源、全局变量(eg.evenbus)等 |
4 routes
软件相关的方法或组件
文件或目录 | 说明 |
---|---|
app_routes | 路由名称或别名 |
app_pages | 路由绑定、初始化首个页面等 |
5 modules
主要页面,比如登录页面、我的页面等
以下为登录页面module
(1) login_bindings
主要为将controller初始化
(2)login_controller
类似于MVC内C层
(3)login_page
登陆页面
三、总结构
- app
- data
- api
- model
- services
- modules
- login_module
- login_bindings
- login_controller
- login_page
- login_module
- routes
- app_routes.dart
- app_pages.dart
- theme
- utils
- values
- utils
- method
- widget
- data
- main.dart