当前位置: 首页 > news >正文

《Flutter篇第一章》基于GetX 和 Binding、Dio 实现的 Flutter UI 架构

架构流程图
lib/
├── app/
│   ├── bindings/           # 依赖注入绑定
│   │   ├── auth_binding.dart
│   │   └── main_binding.dart
│   ├── modules/            # 功能模块
│   │   ├── auth/           # 登录模块
│   │   │   ├── auth_controller.dart
│   │   │   └── auth_page.dart
│   │   └── main/           # 主模块
│   │       ├── tabs/       # 四个Tab页
│   │       │   ├── home/
│   │       │   ├── explore/
│   │       │   ├── cart/
│   │       │   └── profile/
│   │       ├── main_controller.dart
│   │       └── main_page.dart
│   └── routes/             # 路由管理
│       ├── app_pages.dart
│       └── app_routes.dart
├── data/                   # 数据层
│   ├── local/              # 本地存储
│   │   └── storage_service.dart
│   ├── network/            # 网络请求
│   │   ├── api_service.dart
│   │   ├── base_provider.dart
│   │   └── interceptors.dart
│   └── repositories/       # 仓库
│       └── auth_repository.dart
├── core/                   # 核心工具
│   ├── constants/          # 常量
│   │   └── strings.dart
│   └── utils/              # 工具类
│       └── extensions.dart
└── splash_page.dart        # 启动页
架构特点
框架特点分层架构:视图层: 负责UI展示控制器层: 处理业务逻辑仓库层: 聚合数据源服务层: 提供基础能力(网络、存储)状态管理:使用GetX的响应式编程(.obs + Obx())自动内存管理,无需手动dispose细粒度状态更新依赖管理:GetX Binding自动管理依赖生命周期全局服务使用permanent: true保持常驻页面级控制器按需创建路由管理:命名路由系统中间件支持(如登录验证)平滑的页面过渡动画网络模块:Dio封装+拦截器Token自动管理统一错误处理本地存储:GetStorage轻量级键值存储支持对象存储自动序列化/反序列化
实现

1、pubspec.yaml 中配置需要的组件库

  cupertino_icons: ^1.0.2get: ^4.6.5dio: ^5.0.0get_storage: ^2.1.1shared_preferences: ^2.2.1

2、主入口 - lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';import 'app/bindings/initial_binding.dart';
import 'app/routes/app_pages.dart';
import 'app/routes/app_routes.dart';void main() async {WidgetsFlutterBinding.ensureInitialized();await GetStorage.init();SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(systemNavigationBarColor: Colors.transparent,));runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {return GetMaterialApp(title: 'Flutter GetX Template',initialBinding: InitialBinding(),initialRoute: Routes.SPLASH,getPages: AppPages.routes,theme: ThemeData(primarySwatch: Colors.blue),debugShowCheckedModeBanner: false,);}
}

3、lib/splash_page.dart 注释部分可以加入登录判断,也就是token 或者是其他auth

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'app/routes/app_routes.dart';
import 'data/local/storage_service.dart';class SplashPage extends StatelessWidget {const SplashPage({super.key});Widget build(BuildContext context) {Future.delayed(const Duration(seconds: 2), () {final storage = Get.find<StorageService>();// if (storage.token != null) {//   Get.offNamed(Routes.MAIN);// } else {//   Get.offNamed(Routes.LOGIN);// }Get.offNamed(Routes.MAIN);});return const Scaffold(body: Center(child: FlutterLogo(size: 100),),);}
}

4、路由管理 - lib/app/routes/app_routes.dart

abstract class Routes {static const SPLASH = '/';static const LOGIN = '/login';static const MAIN = '/main';
} 

5、 路由配置 - lib/app/routes/app_pages.dart


import 'package:get/route_manager.dart';
import '../../splash_page.dart';
import '../bindings/auth_binding.dart';
import '../bindings/main_binding.dart';
import '../modules/auth/auth_page.dart';
import '../modules/main/main_page.dart';
import 'app_routes.dart';class AppPages {static final routes = [GetPage(name: Routes.SPLASH, page: () => const SplashPage()),GetPage(name: Routes.LOGIN,page: () => AuthPage(),binding: AuthBinding(),),GetPage(name: Routes.MAIN,page: () => MainPage(),binding: MainBinding(),transition: Transition.fadeIn,),];
} 

6、网络请求 - lib/app/data/network/api_service.dart

import 'package:dio/dio.dart';
import 'package:get/get.dart' hide Response;import '../../app/routes/app_routes.dart';
import '../local/storage_service.dart';class ApiService extends GetxService {late Dio _dio;ApiService() {_dio = Dio(BaseOptions(baseUrl: 'https://api.example.com',connectTimeout: 5000.seconds,receiveTimeout: 3000.seconds,));_dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {final token = Get.find<StorageService>().token;if (token != null) {options.headers['Authorization'] = 'Bearer $token';}return handler.next(options);},onError: (error, handler) {if (error.response?.statusCode == 401) {Get.offAllNamed(Routes.LOGIN);}return handler.next(error);},));}Future<Response> get(String path, {Map<String, dynamic>? params}) {return _dio.get(path, queryParameters: params);}Future<Response> post(String path, {dynamic data}) {return _dio.post(path, data: data);}
}

7、本地存储 - lib/app/data/local/storage_service.dart

class StorageService extends GetxService {final _storage = GetStorage();Future<void> saveToken(String token) => _storage.write('auth_token', token);String? get token => _storage.read('auth_token');Future<void> clear() => _storage.erase();
}

8、仓库层 - lib/app/data/repositories/auth_repository.dart

import 'package:get/get.dart';import '../network/api_service.dart';class AuthRepository {final ApiService _apiService = Get.find();Future<Map<String, dynamic>> login(String email, String password) async {final response = await _apiService.post('/auth/login', data: {'email': email,'password': password});return response.data;}
}

9、登录模块绑定 - lib/app/bindings/auth_binding.dart

import 'package:get/get.dart';import '../../data/local/storage_service.dart';
import '../../data/repositories/auth_repository.dart';
import '../modules/auth/auth_controller.dart';class AuthBinding implements Bindings {void dependencies() {Get.lazyPut(() => AuthController(Get.find<AuthRepository>(),Get.find<StorageService>(),));}
}

10、 登录控制器 - lib/app/modules/auth/auth_controller.dart


import 'package:get/get.dart';import '../../../data/local/storage_service.dart';
import '../../../data/repositories/auth_repository.dart';
import '../../routes/app_routes.dart';class AuthController extends GetxController {final AuthRepository _repo;final StorageService _storage;AuthController(this._repo, this._storage);final isLoading = false.obs;Future<void> login(String email, String password) async {try {isLoading(true);final response = await _repo.login(email, password);await _storage.saveToken(response['token']);Get.offAllNamed(Routes.MAIN);} catch (e) {Get.snackbar('Error', 'Login failed');} finally {isLoading(false);}}
}

11、 登录页面 - lib/app/modules/auth/auth_page.dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';import 'auth_controller.dart';class AuthPage extends GetView<AuthController> {final _emailController = TextEditingController();final _passwordController = TextEditingController();AuthPage({super.key});Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Login')),body: Padding(padding: const EdgeInsets.all(20.0),child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [TextField(controller: _emailController,decoration: const InputDecoration(labelText: 'Email'),),const SizedBox(height: 16),TextField(controller: _passwordController,decoration: const InputDecoration(labelText: 'Password'),obscureText: true,),const SizedBox(height: 24),Obx(() => controller.isLoading.value? const CircularProgressIndicator(): ElevatedButton(onPressed: () => controller.login(_emailController.text,_passwordController.text,),child: const Text('Login'),)),],),),);}
}

12、 主模块绑定 - lib/app/bindings/main_binding.dart

import 'package:get/get.dart';import '../modules/main/main_controller.dart';
import '../modules/main/tabs/cart/cart_controller.dart';
import '../modules/main/tabs/explore/explore_controller.dart';
import '../modules/main/tabs/home/home_controller.dart';
import '../modules/main/tabs/profile/profile_controller.dart';class MainBinding implements Bindings {void dependencies() {Get.lazyPut(() => MainController());Get.lazyPut(() => HomeController());Get.lazyPut(() => ExploreController());Get.lazyPut(() => CartController());Get.lazyPut(() => ProfileController());}
}

13、 主控制器 - lib/app/modules/main/main_controller.dart

import 'package:get/get.dart';
class MainController extends GetxController {final RxInt currentIndex = 0.obs;void changeTab(int index) => currentIndex.value = index;
}

14、 主页面 - lib/app/modules/main/main_page.dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';import 'main_controller.dart';
import 'tabs/cart/cart_page.dart';
import 'tabs/explore/explore_page.dart';
import 'tabs/home/home_page.dart';
import 'tabs/profile/profile_page.dart';class MainPage extends GetView<MainController> {final List<Widget> pages = [const HomePage(),const ExplorePage(),const CartPage(),const ProfilePage(),];MainPage({super.key});Widget build(BuildContext context) {return Scaffold(body: Obx(() => pages[controller.currentIndex.value]),bottomNavigationBar: Obx(() => BottomNavigationBar(type: BottomNavigationBarType.fixed, // 设置为fixed类型,否则背景色不生效currentIndex: controller.currentIndex.value,onTap: controller.changeTab,backgroundColor: Colors.white,selectedItemColor: Colors.amber,unselectedItemColor: Colors.black,items: const [BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),BottomNavigationBarItem(icon: Icon(Icons.explore), label: 'Explore'),BottomNavigationBarItem(icon: Icon(Icons.shopping_cart), label: 'Cart'),BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),],),),);}
}

15、 Tab页实现 (以Home页为例) - lib/app/modules/main/tabs/home/home_controller.dart

import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';class HomeController extends GetxController {var welcomeMessage = ''.obs;void onInit() {super.onInit();// 模拟数据加载Future.delayed(const Duration(seconds: 1), () {welcomeMessage.value = 'Welcome back, John!';});}
}

17、 Tab页面 - lib/app/modules/main/tabs/home/home_page.dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';import 'home_controller.dart';class HomePage extends GetView<HomeController> {const HomePage({super.key});Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Home')),body: Center(child: Obx(() => Text(controller.welcomeMessage.value,style: const TextStyle(fontSize: 24),)),),);}
}

17、其他Tab页 (类似实现) 新page都必须按照以下格式写

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'cart_controller.dart';class CartPage extends GetView<CartController> {const CartPage({super.key});Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Cart')),body: const Center(child: Text('Cart Content')),);}
}
import 'package:get/get.dart';class CartController extends GetxController {final welcomeMessage = 'Hello, User!'.obs;void onInit() {super.onInit();}
}

18、 初始化绑定 - lib/app/bindings/initial_binding.dart

import 'package:get/get.dart';import '../../data/local/storage_service.dart';
import '../../data/network/api_service.dart';
import '../../data/repositories/auth_repository.dart';class InitialBinding implements Bindings {void dependencies() {// 持久化服务Get.put(StorageService(), permanent: true);Get.put(ApiService(), permanent: true);// 仓库Get.lazyPut(() => AuthRepository(), fenix: true);}
}
http://www.dtcms.com/a/295624.html

相关文章:

  • 弧焊机器人减少气体消耗攻略
  • 图论:搜索问题
  • C++图论全面解析:从基础概念到算法实践
  • 数据挖掘顶刊TKDE论文分享│ST-LLM+:面向交通预测的图增强时空大语言模型
  • Flutter开发环境搭建与工具链
  • kettle插件-kettle数据挖掘ARFF插件
  • 从手动操作到自动化:火语言 RPA 在多系统协作中的实践
  • GoLand 项目从 0 到 1:第二天 —— 数据库自动化
  • postgresql执行创建和删除时遇到的问题
  • JVM 核心内容
  • k8s之Ingress服务接入控制器
  • 函数耗时情况检测方案
  • LeetCodeOJ题:回文链表
  • HTTP/1.0、HTTP/1.1 和 HTTP/2.0 主要区别
  • Java设计模式之行为型模式(中介者模式)介绍与说明
  • 常用设计模式系列(十一)—外观模式
  • VUE2 学习笔记5 动态绑定class、条件渲染、列表过滤与排序
  • 微服务-springcloud-springboot-Skywalking详解(下载安装)
  • C++中std::list的使用详解和综合实战代码示例
  • Linux进程间通信:管道机制全方位解读
  • uniapp转微信程序点击事件报错Error: Component “xx“ does not have a method “xx“解决方案
  • Linux724 逻辑卷挂载;挂载点扩容;逻辑卷开机自启
  • 【PZ-ZU7EV-KFB】——ZYNQ UltraScale + ZU7EV开发板ARM/FPGA异构计算开发平台,赋能多域智能硬件创新
  • The Missing Semester of Your CS Education 学习笔记以及一些拓展知识(六)
  • 从“类”到“道”——Python 面向对象编程全景解析
  • J2EE模式---组合实体模式
  • 从指标定义到AI执行流:衡石SENSE 6.0的BI PaaS如何重构ISV分析链路
  • 【推荐100个unity插件】Animator 的替代品?—— Animancer Pro插件的使用介绍
  • Mac电脑使用IDEA启动服务后,报service异常
  • 微算法科技(NASDAQ: MLGO)研究量子信息递归优化(QIRO)算法,为组合优化问题拓展解决新思路