flutter 使用getx + dio + mvvm 搭建一个架子

1,188 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情

MVVM 架构

image.png

职责:

  • View 视图显示
  • Controller 控制器,大管家,各种生命周期、数据装备、路由...
  • DataModel 数据模型
  • ViewModel 负责数据发生变化时去更新 View 视图
getx + dio + mvvm

image.png

说明:

  • View 视图中加载控制器 Controller
  • 控制器 Controller生命周期载入数据
  • View 视图触发控制器 Controller 方法改变数据
  • 数据 ViewModel 触发更新视图
  • Model 数据模型拉取远程数据或者本地数据
分层代码生成与理解

创建 login 模块

我们创建了一个 login 的模块,文件清单如下

image.png

名称说明
index.dart导包
controller.dart控制器 业务逻辑
state.dart数据
view.dart视图
bindings.dart路由懒加载
widgets子组件

img

发现通过这样的方式,将代码的层级关系进行了拆分,代码的逻辑会更加清楚,便于维护

阅读理解代码

state.dart

import 'package:get/get.dart';

class LoginState {
  // title
  final_ title = "".obs;
  set title(value) =>_ title.value = value;
  get title =>_ title.value;
}

controller.dart

import 'package:get/get.dart';

import 'index.dart';

class LoginController extends GetxController {
  LoginController();

  final state = LoginState();

  // tap
  void handleTap(int index) {
    Get.snackbar(
      "标题",
      "消息",
    );
  }

  /// 在 widget 内存中分配后立即调用。
  @override
  void onInit() {
    super.onInit();
  }

  /// 在 onInit() 之后调用 1 帧。这是进入的理想场所
  @override
  void onReady() {
    super.onReady();
  }

  /// 在 [onDelete] 方法之前调用。
  @override
  void onClose() {
    super.onClose();
  }

  /// dispose 释放内存
  @override
  void dispose() {
    super.dispose();
  }
}

view.dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';

import 'index.dart';
import 'widgets/widgets.dart';

class LoginPage extends GetView<LoginController> {
  const LoginPage({Key? key}) : super(key: key);

  // 内容页
  Widget_ buildView() {
    return const HelloWidget();
  }

  @override
  Widget build(BuildContext context) {
    return GetBuilder<LoginController>(
      builder: (_) {
        return Scaffold(
          appBar: AppBar(title: const Text("login")),
          body: SafeArea(
            child: _buildView(),
          ),
        );
      },
    );
  }
}

bindings.dart

import 'package:get/get.dart';

import 'controller.dart';

class LoginBinding implements Bindings {
  @override
  void dependencies() {
    Get.lazyPut<LoginController>(() => LoginController());
  }
}

widgets/hello.dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../index.dart';

/// hello
class HelloWidget extends GetView<LoginController> {
  const HelloWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Obx(() => Text(controller.state.title)),
    );
  }
}

在绑定路由时, binding 中加入你的模块依赖

GetPage(
      name: RouteNames.login,
      page: () => const LoginPage(),
      binding: LoginBinding(),
    ),

创建路由

// 路由 Pages
class RoutePages {
  // 列表
  static List<GetPage> list = [
    GetPage(
      name: "/",
      page: () => const LoginPage(),
      binding: LoginBinding(),
    ),
  ];
}

在main.dart中使用创建的路由

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),

      // 路由
      initialRoute: "/",
      getPages: RoutePages.list,

      // home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}