Warehouse address: github.com/xieyezi/flu…
Said in the previous
Hi, long time no see, this time I bring a practical article about Flutter + getx.
The new Flutter GetX template, based on getX implementation, is suitable for medium to large project development.
- 💥
flutter
Latest version of air security - 🍀
view
和logic
Completely decoupled - ⚡
view
和state
Automatic response - 📦
dio
,shared_preferences
And other general module encapsulation - 🔥 to
context
the
The environment
Flutter 2.2.0, channel stable, https://github.com/flutter/flutter.git Framework, revision b22742018b (3 weekes line) Engine • Revision A9D88A4D18 Tools • Dart 2.13.0Copy the code
Lib directory partition
common
This directory is used to store generic modules and their variables, such as colors, Langs, values, etc., for example:
├── bass exercises ── bass exercises ── bass exercises ── bass exercises ── bass exercises ── bass Exercises ── ├── lessons.├ ─ lessons.├Copy the code
components
This directory mainly houses the top-level bulletin components such as AppBar, scaffold, Dialog, etc. For example:
├── ├─ Bass exercises ── Bass exercisesCopy the code
pages
This directory mainly stores page files, for example:
Note: Each Item is a folder.
├─ Index ├─ home ├─ login ├─ proxy ├─ splashCopy the code
router
This directory is a routing file. The routing mode convention of this template is named route, which is a fixed directory. The directory structure is as follows:
├ ─ ─ app_pages. Dart └ ─ ─ app_routes. The dartCopy the code
services
This directory is used to store apis such as:
├─ services. ├─ user //Copy the code
utils
This directory is used to store utility modules such as request, local_storage, etc., for example:
├── Authentication.Bass Exercises ── ├─ Authentication.bass Exercises ── Bass.Bass Exercises ── Bass.bass ExercisesCopy the code
The development of specification
When you need to create a new page, you need to follow these steps:
Suppose we now want to create a Home page.
- in
pages
Creating a Directoryhome
Directory:
// pages
$ mkdir home
$ cd home
Copy the code
- in
home
Under the directory, create the following four files:
-
Home_view.dart: view (for page layout)
-
Home_contrler. dart: controller (used to implement business logic)
-
Home_binding: controller binding (used to bind controller to view)
-
Home_model: data model (used to contract data models)
Note: this must be done every time a page is created, with the form ‘page name_key’.
When you have created a page, the directory should look like 👇 :
/ / home. ├ ─ ─ home. Binding. The dart ├ ─ ─ home_controller. Dart ├ ─ ─ home_model. Dart └ ─ ─ home_view. The dartCopy the code
- to
router
Add route to folder:
// app_routes.dart
part of 'app_pages.dart';
abstract class AppRoutes {...static const Home = '/home'; . }Copy the code
// app_pages.dart
class AppPages {
static finalroutes = [ ... GetPage( name: AppRoutes.Home, page: () => HomePage(), binding: HomeBinding(), ), ... ] ; }Copy the code
Complete the steps above, and you’ll be happy to start developing.
State management
Contrller is where we implement our business logic, so why do we separate business logic from view? Because the spaghetti code of flutter was too difficult to maintain, the layout and style of a flutter page were disgusting, and the business logic code was too difficult to maintain. Moreover, if we wanted to have state, our pages had to inherit from stateful widgets. There is too much performance loss.
So we use the Controller provided by GetX to decouple our business logic from our view.
A standard Contrller looks like this:
class HomeController extends GetxController {
final count = 0.obs;
@override
void onInit() {
super.onInit();
}
@override
void onReady() {}
@override
void onClose() {}
void increment() => count.value++;
}
Copy the code
When we need a responsive variable, we simply add a. Obs to the end of the variable, for example:
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;
// Even custom classes - can be any class
final user = User().obs;
Copy the code
Note that since the flutter now has null-safety, it is best to give the response variable an initial value.
When we update the reactive variable in controller, the view automatically updates the render.
But in practice, you don’t have to define reactive variables, for example:
class HomeController extends GetxController {
int count = 0;
@override
void onInit() {
super.onInit();
}
@override
void onReady() {}
@override
void onClose() {}
voidincrement() { count++; update(); }}Copy the code
The only difference between this and.obs is that we need to manually call update() to update the state change so that the view can be notified to rerender when the count changes.
We could put the request into an onInit hook, so for example, we could get the order information when we went to the order page, just like the init hook in stateful Wdiget.
view
First, you need to inherit your class from GetxView
(T is your Controller), for example:
class HomePage extends GetView<HomeController> {
HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
returnScaffold( body: Container(), ); }}Copy the code
GetxView
will automatically inject Controller into the view for you. You can simply say that it automatically does the following for you
final controller = Get.find<HomeController>();
Copy the code
Don’t worry about the performance of GetxView
because it simply inherits the Stateless Widget. Remember, with GetX you don’t need Stateful widgets at all
When we want to bind controller variables, we agree on two methods:
Obx(()=>)
If your variable is.obs, then we use Obx(()=>), which automatically refreshes the view when the variable changes, for example:
// 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++;
}
Copy the code
Use Obx(()=>) to bind count inside view:
// home_view
class HomePage extends GetView<HomeController> {
HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
returnScaffold( body: Container( child: Obx(() => Center(child: Text(controller.count.toString()))), ), ); }}Copy the code
GetBuilder<T>
If your variable is not.obs, then we use GetBuilder
, for example:
class HomeController extends GetxController {
int count = 0;
@override
void onInit() {
super.onInit();
}
@override
void onReady() {}
@override
void onClose() {}
voidincrement() { count++; update(); }}Copy the code
Use GetBuilder
to bind count in the view:
class HomePage extends GetView<HomeController> {
HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BaseScaffold(
appBar: MyAppBar(
centerTitle: true,
title: MyTitle('home'),
leadingType: AppBarBackType.None,
),
body: Container(
child: GetBuilder<HomeController>(builder: (_) {
returnCenter(child: Text(controller.count.toString())); }),),); }}Copy the code
Getx provides other render functions as well, but to reduce the mental burden and complexity, these two will suffice.
Routing management
Here we use the named routing provided by GetX, and if you have learned VUE, there is almost no learning cost.
Suppose we now add a page called List, and we need to configure it under the Router folder:
// app_routes.dart
part of 'app_pages.dart';
abstract class AppRoutes {...static const List = '/list'; . }Copy the code
// app_pages.dart
class AppPages {
static finalroutes = [ ... GetPage( name: AppRoutes.Home, page: () => ListPage(), binding: ListBinding(), ), ... ] ; }Copy the code
The assumption corresponding to this List is the order List. When we click an order in the List, we will usually enter the order detail page, so we should add another detail page at this time:
// app_routes.dart
part of 'app_pages.dart';
abstract class AppRoutes {...static const List = '/list';
static const Detaul = '/detail'; . }Copy the code
// app_pages.dart
class AppPages {
static finalroutes = [ ... GetPage( name: AppRoutes.Home, page: () => ListPage(), binding: ListBinding(), children: [ GetPage( name: AppRoutes.Detail, page: () => DetailPage(), binding: DetailBinding(), ), ], ), ... ] ; }Copy the code
Because the Detail page and the List page have a hierarchy, we can put the Detail page under the children in the List, but you don’t have to do that.
When we use:
Get.toNamed('/list/detail');
Copy the code
Other routing hooks:
Browse and delete the previous page:
Get.offNamed("/NextScreen");
Copy the code
Browse and delete all previous pages:
Get.offAllNamed("/NextScreen");
Copy the code
Pass parameters:
Get.toNamed("/NextScreen", arguments: {id: 'xxx'});
Copy the code
The type of the argument can be a string, a Map, a List, or even an instance of a class.
Get parameters:
print(Get.arguments);
// print out: `{id: 'xxx'}`
Copy the code
Route using getx it has a nice advantage that it is contextualized. Remember how we used to fear being dominated by context? With GetX, it will cease to exist.
usemonia-cliTo develop
We are happy to add flutter- gex-Template to monia-CLI.
Create a Flutter project using monia-CLI:
monia create <project-name>
Copy the code
➜ 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 ? Both Please input the 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 _ _ _ _ __ ___ ___ _ __ (_) __ _ ___| (_) | '_ ` _ \ / _ \| '_ \| |/ _` |_____ / __| | | | | | | | | (_) | | | | | (_ | | | _____ (__ | | | | _ | | _ | | _ | \ ___ / | _ | | _ _ - | | \ __, _ | \ ___ | _ _ - | |Copy the code
Not only that, monia-CLI also provides the ability to quickly generate a Flutter Getx page.
If you now want to generate a new order_sending page, you simply type under the Pages directory:
monia init order_sending
Copy the code
➜ 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.Copy the code
Vscode plug-in
Monia also provides the vscode plug-in: monia-vscode-extension
Create a Flutter getx Page in the Pages directory by clicking on the monia-generate text button in the lower left corner and entering pageName:
The official link
Status management Route management dependency management