• Stars
    star
    212
  • Rank 186,122 (Top 4 %)
  • Language
    Dart
  • Created over 3 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

flutter 2.x and getx v4.x template

flutter_getx_template

Language: 中文简体 | English

visitors null safety flutter version getx version

基于getx 实现的全新flutter getx 模版,适用于中大型项目的开发。

  • 💥 flutter最新版本的空安全
  • 🍀 view逻辑 完全解耦
  • viewstate 自动响应
  • 📦 dioshared_preferences等通用模块的封装
  • 🔥context

环境

Flutter 2.2.0 • channel stable • https://github.com/flutter/flutter.git
Framework • revision b22742018b (3 weeks ago) • 2021-05-14 19:12:57 -0700
Engine • revision a9d88a4d18
Tools • Dart 2.13.0

lib目录划分

  • common

此目录用来存放通用模块及其变量,例如colorslangsvalues等,例如:

├── colors
│   └── colors.dart
├── langs
│   ├── en_US.dart
│   ├── translation_service.dart
│   └── zh_Hans.dart
└── values
    ├── cache.dart
    ├── storage.dart
    └── values.dart
  
  • components

此目录主要存放顶层公告组件,例如 appbarscaffolddialog等等,例如:

├── components.dart
├── custom_appbar.dart
└── custom_scaffold.dart
  • pages

此目录主要存放页面文件,例如:

注:每个Item为一个文件夹.

├── Index
├── home
├── login
├── notfound
├── proxy
└── splash

  • router

此目录为路由文件,此模版的路由方式约定为命名路由,为固定目录,目录结构如下:

├── app_pages.dart
└── app_routes.dart

  • services

此目录用来存放API,例如:

├── services.dart
└── user.dart  // 关于用户的API
  • utils

此目录用来存放一些工具模块,例如 requestlocal_storage等等,例如:

├── authentication.dart
├── local_storage.dart
├── request.dart
├── screen_device.dart
└── utils.dart

开发规范

当你需要新建一个页面时,你需要按照以下步骤进行:

假设我们现在要创建一个Home 页面.

  1. pages 目录下新建home 目录:
// pages

$ mkdir home
$ cd home
  1. home 目录下,新建以下四个文件:
  • home_view.dart : 视图(用来实现页面布局)

  • home_contrller.dart : 控制器(用来实现业务逻辑)

  • home_binding : 控制器绑定(用来绑定controllerview)

  • home_model : 数据模型(用来约定数据模型)

注意:每创建一个页面时,都必须如此做,命名采用 '页面名_key' 这样的形式。

当你创建好一个页面,目录应该长这样👇

// home
.
├── home.binding.dart
├── home_controller.dart
├── home_model.dart
└── home_view.dart
  1. router文件夹下面添加对应路由:
// app_routes.dart
part of 'app_pages.dart';
abstract class AppRoutes {
  ...
  static const Home = '/home';
  ...
}
// app_pages.dart
class AppPages {

  static final routes = [
    ...
    GetPage(
      name: AppRoutes.Home,
      page: () => HomePage(),
      binding: HomeBinding(),
    ),
    ...
  ];
}

完成以上步骤,你就可以愉快的开始开发了。

状态管理

contrller 是我们实现业务逻辑的地方,为什么我们要将 业务逻辑和视图分开呢?因为flutter 的意大利面式的代码实在是太难维护了,本来flutter 的页面布局和样式写在一起就很恶心了,再加上业务逻辑代码的话,实在太难以维护,而且,如果我们想要拥有状态的话,我们的页面不得不继承自stateful widget,性能损耗太严重了。

所以我们利用 getx 提供的 controller,将我们的业务逻辑和视图解耦。

一个标准的contrller长这样:

class HomeController extends GetxController {
  final count = 0.obs;

  @override
  void onInit() {
    super.onInit();
  }

  @override
  void onReady() {}

  @override
  void onClose() {}

  void increment() => count.value++;
}

当我们需要一个响应式的变量时,我们只需在变量的后面加一个.obs,例如:

final name = ''.obs;
final isLogged = false.obs;
final count = 0.obs;
final balance = 0.0.obs;
final number = 0.obs;
final items = <String>[].obs;
final myMap = <String, int>{}.obs;

// 甚至自定义类 - 可以是任何类
final user = User().obs;

值得注意的是,因为现在flutter 有了null-safety,所以我们最好给响应式变量一个初始值。

当我们在controller更新了响应式变量时,视图会自动更新渲染。

但是实际上,你也可以不定义这种响应式变量,例如我们可以这样:

class HomeController extends GetxController {
  int count = 0;

  @override
  void onInit() {
    super.onInit();
  }

  @override
  void onReady() {}

  @override
  void onClose() {}

  void increment() {
    count++;
    update();
  } 
}

这样和.obs的唯一区别是,我们需要手动调用 update() 更新状态的变化,这样view才能在count变化时,收到我们的通知重新渲染。

我们应该将发起请求,放在onInit钩子里面,例如进入订单页面时,我们应该获取订单信息,就如同在 stateful wdiget 里面的init钩子一样。

视图

首先,你需要将你的class 继承自 GetxView<T>(T 为你的Controller),例如:

class HomePage extends GetView<HomeController> {
  HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(),
    );
  }
}

GetxView<HomeController> 会自动帮你把 Controller 注入到 view 中,你可以简单理解为它自动帮你执行了以下步骤

final controller = Get.find<HomeController>();

不必担心 GetxView<T> 的性能,因为它仅仅是继承自 Stateless Widget ,记住,有了 getx 你完全不需要 Stateful Widget

当我们想要绑定controller的变量时,我们约定了两种方法:

  1. Obx(()=>)

如果你的变量是.obs的,那么我们就使用Obx(()=>),它会在变量变更时自动刷新view,例如:

// home_contrller
class HomeController extends GetxController {
  final count = 0.obs;

  @override
  void onInit() {
    super.onInit();
  }

  @override
  void onReady() {}

  @override
  void onClose() {}

  void increment() => count.value++;
}

view里面使用 Obx(()=>) 绑定count:

// home_view
class HomePage extends GetView<HomeController> {
  HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: Obx(() => Center(child: Text(controller.count.toString()))),
      ),
    );
  }
}
  1. GetBuilder<T>

如果你的变量不是.obs的,那么我们就使用GetBuilder<T>,例如:

class HomeController extends GetxController {
  int count = 0;

  @override
  void onInit() {
    super.onInit();
  }

  @override
  void onReady() {}

  @override
  void onClose() {}

  void increment() {
    count++;
    update();
  } 
}

view 里面使用 GetBuilder<T> 绑定count:

class HomePage extends GetView<HomeController> {
  HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BaseScaffold(
      appBar: MyAppBar(
        centerTitle: true,
        title: MyTitle('首页'),
        leadingType: AppBarBackType.None,
      ),
      body: Container(
        child: GetBuilder<HomeController>(builder: (_) {
          return Center(child: Text(controller.count.toString()));
        }),
      ),
    );
  }
}

其实getx还提供了其他的render function,但是为了减少心智负担和复杂度,我们就使用这两种就够了。

路由管理

这里我们采用了getx提供的命名式路由,如果你学过vue,那么几乎没有学习成本。

假设我们现在添加了一个页面,叫做List,然后我们需要到router文件夹下面去配置它:

// app_routes.dart
part of 'app_pages.dart';
abstract class AppRoutes {
  ...
  static const List = '/list';
  ...
}
// app_pages.dart
class AppPages {

  static final routes = [
    ...
    GetPage(
      name: AppRoutes.Home,
      page: () => ListPage(),
      binding: ListBinding(),
    ),
    ...
  ];
}

这个List对应的假设是订单列表,当我们点击列表中某个订单时,我们通常会进入到订单详情页面,所以我们此时应再添加一个详情页面:

// app_routes.dart
part of 'app_pages.dart';
abstract class AppRoutes {
  ...
  static const List = '/list';
  static const Detaul = '/detail';
  ...
}
// app_pages.dart
class AppPages {

  static final routes = [
    ...
    GetPage(
      name: AppRoutes.Home,
      page: () => ListPage(),
      binding: ListBinding(),
      children: [
        GetPage(
          name: AppRoutes.Detail,
          page: () => DetailPage(),
          binding: DetailBinding(),
        ),
      ],
    ),
    ...
  ];
}

因为详情页面和列表页面有先后级关系,所以我们可以将 Detail 页面,放到 Listchildren 下面,当然你也可以不这样做。

当我们使用时:

Get.toNamed('/list/detail');

其他路由钩子:

浏览并删除前一个页面:

Get.offNamed("/NextScreen");

浏览并删除所有以前的页面:

Get.offAllNamed("/NextScreen");

传递参数:

Get.toNamed("/NextScreen", arguments: {id: 'xxx'});

参数的类型可以是一个字符串,一个Map,一个List,甚至一个类的实例。

获取参数:

print(Get.arguments);
// print out: `{id: 'xxx'}`

使用 getx 的路由它有一个非常好的优点,那就是它是去context化的。还记得我们以前被context 支配的恐惧吗? 有了getx,它将不复存在。

使用 monia-cli 进行开发

我们很高兴,能将 flutter-getx-template 加入到 monia-cli

利用 monia-cli 新建flutter项目:

monia create <project-name>
➜  Desktop monia create flutter_demo
? Which framework do you want to create Flutter
? Which flutter version do you want to create null-safety
? Please input your project description description
? Please input project version 1.0.0

✨  Creating project in /Users/xieyezi/Desktop/flutter_demo.

🗃  Initializing git repository....
.......
⠏ Download template from monia git repository... This might take a while....

🎉  Successfully created project flutter_demo.
👉  Get started with the following commands:

$ cd flutter_demo
$ flutter run

                        _                  _ _ 
  _ __ ___   ___  _ __ (_) __ _        ___| (_)
 | '_ ` _ \ / _ \| '_ \| |/ _` |_____ / __| | |
 | | | | | | (_) | | | | | (_| |_____| (__| | |
 |_| |_| |_|\___/|_| |_|_|\__,_|      \___|_|_|

不仅如此, monia-cli 还提供了快速生成一个 flutter getx 页面的功能。

假如现在你想生成一个 order_sending 新页面,你只需在 pages 目录下面输入:

monia init order_sending
➜  pages monia init order_sending
✨  Generate page in /Users/xieyezi/Desktop/flutter_demo/lib/pages/order_sending.
⠋ Generating, it's will not be wait long...
generate order_sending lib success.
generate /Users/xieyezi/Desktop/flutter_demo/lib/pages/order_sending/order_sending_view.dart file success.
generate /Users/xieyezi/Desktop/flutter_demo/lib/pages/order_sending/order_sending_controller.dart file success.
generate /Users/xieyezi/Desktop/flutter_demo/lib/pages/order_sending/order_sending_binding.dart file success.

🎉  Successfully generate page order_sending.

vscode 插件

monia 还提供了vscode 插件: monia-vscode-extension

点击左下角的monia-generate 文字按钮,输入pageName,即可在pages目录下新建一个flutter getx page

example.gif

官方链接

状态管理 路由管理 依赖管理

More Repositories

1

flutter-shopping-AiRi

一款基于Flutter开发的购物App,涵盖了购物App的常见功能
Dart
395
star
2

sku-algorithm

商品多规格选择-sku算法
TypeScript
121
star
3

semi-design-pro

基于semi-design构建的admin管理系统
TypeScript
84
star
4

monia-cli

一个同时支持Vue、React、Flutter的项目脚手架
TypeScript
75
star
5

vueMusic

vue做的web音乐App
Vue
71
star
6

flutter-Anniversary

一款界面优美,功能简洁的纪念日APP
Dart
71
star
7

2019-nCoV-Virus

新型冠状病毒-实时疫情-数据可视化-React版本
JavaScript
61
star
8

2019-ncov-vue3-version

新型冠状病毒实时疫情 Vue-Compostion-Api版本 (Vue3 + TypeScript)
Vue
55
star
9

vue3-shopping-airi

一款基于 vue3+ typescript + vite + genji + tailwindcss 开发的购物 H5 App,涵盖了购物App的常见功能
Vue
20
star
10

NeteaseMusicWorkFolwForAlfred

网易云音乐Alfred命令行控制器
AppleScript
17
star
11

xyz-city-picker

flutter 地址选择器
Dart
15
star
12

vuepress-blog

vuepress 个人博客😽发布在github pages
JavaScript
14
star
13

genji

a vue state management framewok by vue3 reactivity
TypeScript
14
star
14

QQmusicWorkFlowForAlfred

QQ音乐Alfred命令行控制器
AppleScript
14
star
15

generateResume

输入个人信息,自动生成多份优美简历
Vue
11
star
16

Book-ticket

航班订票微信小程序
JavaScript
11
star
17

vae-ui

vue3 UI 组件库
SCSS
10
star
18

upload-pgyer

一款上传apk/ipa文件到蒲公英并通知到指定群的工具(同时支持钉钉、飞书、企业微信)
TypeScript
10
star
19

react-vite-admin

Management system with react, vite, zustand, ant-design and typescript.
TypeScript
9
star
20

website-hexo-2022

个人博客netlify版本,由于Netlify访问过慢,故现在主要用作博客备份
7
star
21

vite-vue3-react-svelte-todo-app

one vite + vue3 + react + svelte todo App.
TypeScript
7
star
22

react-demo

从0到1搭建react项目,支持redux、dva、connect-react-router、react-router-dom、react-redux
TypeScript
5
star
23

xieyezi.github.io

github pages
HTML
5
star
24

Internet_cafe_management

大三下做的网吧管理系统
JavaScript
5
star
25

vue-template

vue-template for monia-cli
Vue
4
star
26

2016-courseDesign2

c51
C
4
star
27

FontForCode

包括Fira_Code和Operator Mono两种字体,将其应用在VScode.
4
star
28

Library

图书馆管理系统
Java
4
star
29

flutter-template

flutter template for monia-cli
Dart
4
star
30

next-website

TypeScript
3
star
31

my-c-programs

2015秋C语言课程设计
C++
3
star
32

vue-vite-template

vue-vite-template for monia-cli
TypeScript
3
star
33

my-java-programes

我的java程序练习题
Java
3
star
34

Xydesign

计算机程序设计大赛参赛作品
CSS
3
star
35

cra-template-xieyezi

create-react-app tempate of typescript
TypeScript
3
star
36

KoaWithTypeScript

GraphQL Wtih Koa and TypeScript
TypeScript
3
star
37

react-template

react-template for monia-cli
TypeScript
3
star
38

vue3-demo

vue3尝鲜
Vue
3
star
39

xieyezi

my profile
3
star
40

xieyziLyricFormat

一个能够将字符串类型的歌词数据解析为对象的NPM包
JavaScript
3
star
41

xieyezi-cli

a vue and React cli
JavaScript
3
star
42

webStorage

一个将localStorage和sessionStorage统一封装的NPM包
JavaScript
3
star
43

customer-admin

TypeScript
3
star
44

es6-vuepress-version

es6标准入门-vuepress版本
HTML
3
star
45

laomeng_blog

老孟flutter网站demo
HTML
3
star
46

lyra-cn

a tool for offline search Chinese.
TypeScript
1
star