Flutter : Wings 文件结构
关于Wings
Wings 是一个基于 getx 构建的 MVC 文件结构,用于 flutter 项目。旨在减少开发时间,提高程序员的生产力。
文件结构
-
core
-
immutable(不可变)
此文件夹包含 Wings 的核心,不应进行编辑。
-
mutable(可变)
-
-
features(功能)
您可以在此处按照推荐的结构(MVC)添加您的应用功能。
- featureName(功能名称)
- 控制器
- model
- view(视图)
- featureName(功能名称)
安装
将项目克隆到您的设备
git clone https://github.com/Invention-Technology/Flutter-Wings.git
进入项目目录并运行 flutter pub get 以安装所有依赖项。
简单使用
1- 在 features 文件夹内创建一个新文件夹,并将其命名为您的功能名称,此处我们称之为 home。
2- 创建三个名为:controller、model 和 view 的文件夹。
3- 打开 model 文件夹,创建一个名为:home.model.dart 的新文件,并在其中添加以下代码:
import 'package:wings/core/immutable/base/models/model.wings.dart';
class HomeModel implements WingsModel {
dynamic id; // add all the properties that will be fetched from the API and will be used inside the view
dynamic title;
HomeModel({
this.id,
this.title,
});
@override
List<WingsModel> fromJsonList(List<dynamic> json) {
List<HomeModel> models = [];
for (var element in json) {
models.add(HomeModel.fromJson(element));
}
return models;
}
factory HomeModel.fromJson(Map<String, dynamic> json) {
// add all the properties that you added above to assign the data that came from json to this instance
return HomeModel(id: json['id'], title: json['title']);
}
@override
WingsModel fromJson(Map<String, dynamic> json) {
return HomeModel.fromJson(json);
}
@override
Map<String, dynamic> toJson() {
// Map the data of this instance to json object to be send to the API
return {
'id': id,
'title': title,
};
}
}
4- 打开 controller 文件夹,创建一个名为:home.controller.dart 的新文件,并在其中添加以下代码:
import 'package:wings/core/immutable/base/controllers/controller.wings.dart';
import 'package:wings/core/immutable/providers/remote/request.wings.dart';
import 'package:wings/core/mutable/remote/urls.wings.dart';
import 'package:wings/features/index/model/index.model.dart';
class HomeController extends WingsController {
List<HomeModel> get posts => data;
@override
void onInit() async {
model = HomeModel(); // the model that coresponsidng to this feature
request = WingsRequest(url: WingsURL.home, shouldCache: true); // request data using REST API with the option caching the response
super.onInit();
}
}
5- 打开 view 文件夹,创建一个名为:home.view.dart 的新文件,并在其中添加以下代码:
import 'package:flutter/material.dart';
import 'package:wings/core/immutable/base/views/view.wings.dart';
class HomeView extends WingsView<HomeController> {
HomeView({Key? key}) : super(key: key, controller: HomeController());
@override
Widget successState(BuildContext context) {
return Text(controller.posts[0].title); // Title of the first post that came from the API
}
}
有关更多信息,请参阅 features 文件夹内提供的示例。
高级使用
主题
您可以通过进入 core/mutable/themes/theme.wings.dart 来自定义您的主题。
翻译
Wings 通过 GetX 的翻译功能支持两种默认语言:ar 和 en。
-
为每种语言添加一个新文件,名称分别为
your_file.en.dart和your_file.ar.dart。 -
您的文件应具有以下结构:
// each key should start with the file name capitalized camel case then : then the key capitalized camel case final Map<String, String> errorEn = { 'Error:ServerException': "Oops! We couldn't connect to the server", 'Error:CacheException': 'No Internet Connection', };
-
将您刚刚添加的变量添加到文件
_en.trans.dart中。import 'common.en.dart'; import 'error.en.dart'; import 'feedback.en.dart'; // add the variable name for each file ex: errorEn with spread operator final Map<String, String> en = { ...errorEn, ...commonEn, ...feedbackEn, };
-
现在您可以向您的项目添加翻译键,但不要删除现有的翻译,您可以更改翻译本身。
-
您可以通过更改默认语言来更改默认语言。
Wings.instance.defaultLanguage = WingsLanguage(locale: const Locale('ar'), textDirection: TextDirection.rtl);
状态
Wings 为每种用途提供了多种状态:Loading(加载)、Error(错误)、Success(成功)、ErrorFlushBar(错误提示条)、SuccessFlushBar(成功提示条),并且可以自定义每一种。
您可以在 emutable/widgets/state 和 emutable/helper/snack_bar 中更改每种状态的设计,并且可以添加您的自定义小部件或助手,并通过覆盖 mutable/widgets/states/app_state.wings.dart 中的默认状态。
import 'package:flutter/material.dart';
import '../../../immutable/providers/errors/error.model.wings.dart';
import '../../helpers/snack_bar/error_snack_bar.helper.wings.dart'
as error_snack_bar;
import '../../helpers/snack_bar/success_snack_bar.helper.wings.dart'
as success_snack_bar;
import 'error_state.widget.wings.dart';
import 'loading_state.widget.wings.dart';
class WingsAppState {
static Widget defaultWidgetState() {
return loading();
}
static Widget errorState({onRefresh, error}) {
return WingsErrorState(
onRefresh: onRefresh,
error: error,
);
}
static Widget loading() {
return const LoadingState();
}
static void successSnackBar({String message = '', String title = ''}) {
success_snack_bar.successSnackBar(message: message, title: title);
}
static void errorSnackBar({ErrorModel? error}) {
error_snack_bar.errorSnackBar(error: error);
}
}
远程
Wings 使用 REST API,不使用 patch 请求,因为并非所有服务器都支持 patch 请求。
您可以在 mutable/remote/urls.wings.dart 中添加您的 API URL。
class WingsURL {
static String get baseURL => 'https://jsonplaceholder.typicode.com/';
static String get posts => 'posts';
}
如果您有自定义响应格式,其中数据附带额外信息,您可以将您的规则添加到 mutable/remote/response_format.wings.dart 中。
import 'dart:convert';
class WingsResponseFormat {
static String? key;
/// This function will check if the response is valid
/// according to the json structure that has been agreed on between
/// the backend and the flutter developer
///
/// The default wings validated response is according to JSON-API:
/// {"data": {...}}
///
/// This function require back-end api to always fill the data parameter
/// in the json response
///
/// if you don't like this json response,
/// please change this function to always return true without checking any code
/// static bool validatedResponse(String response) { return true; }
static bool validatedResponse(String response) {
return true; // TODO: uncomment this line if you don't have custom format
try {
key = 'data';
var data = jsonDecode(response);
if (data[key].toString().isEmpty) {
return false;
}
return true;
} catch (exception) {
return false;
}
}
}
要发送任何请求,您必须使用 WingsRequest 类来指定请求信息:url(URL)、body(请求体)、header(请求头)、queryString(查询字符串)。
request = WingsRequest(
url: url,
shouldCache: true,
body: {
"email":'[email protected]',
'password':"password"
},
);
在您的 controller 中,您可以使用 getData()、sendData() 来获取/发送数据。这些方法将读取 request 变量并为您处理其余事务。
void login(){
request = WingsRequest(
url: WingsURL.login,
body: {
"email":'[email protected]',
'password':"password"
},
);
sendData();
}
您可以通过 provider 访问更多方法。您有四种方法来处理请求:provider.get(request: request)、provider.insert(request: request)、provider.delete(request: request)、provider.update(request: request)。
Statics(静态)
静态变量的目的是避免在多个地方使用字符串时出现拼写错误。
Wings 结构使用
WingsFeedback、WingsErrorAssets作为静态变量。
自定义请求消息/资源
您可以自定义请求消息(成功和失败)以及资源。
- 要自定义请求消息,请转到
mutable/statics/feedback.static.dart。
class WingsFeedback {
static String insertSuccess = 'Success:Insert'.tr;
}
- 要自定义请求异常的图标和图片,请转到
mutable/statics/error_asset.static.wings.dart。
class WingsErrorAssets {
// Just in case that some icons or images deleted or not found, use those default values to handle the errors that may arise
static String defaultImage = 'assets/images/error.png';
static String defaultIcon = 'assets/icons/error.svg';
static String unexpectedErrorImage = '';
static String unexpectedErrorIcon = '';
//................
}
存储
您可以存储希望在应用程序生命周期中存储和检索的数据。
class WingsStore {
// add your data
}
助手
项目中常用的所有辅助函数,并且它们具有依赖任务,都可以移到此处。
小部件
项目中常用的所有小部件,并且它们具有依赖任务,都可以移到此处。
状态
Wings 使用
mutable/widgets/states中的小部件,因为它们在整个结构中被广泛使用,并且可以由开发人员自定义。