GetX:SuperController

  1. 什么是 SuperController
  2. 案例
  3. StateMixin和SuperController
  4. SuperController的生命周期
    1. 生命周期图

什么是 SuperController

SuperController 是 GetX 提供的一个 抽象控制器类,它扩展了普通的 GetxController,可以直接处理:

  • 数据状态(加载、成功、空、错误)
  • 请求结果缓存
  • 网络请求刷新(refresh / retry)

它的核心是和 RxStatus 搭配使用,类似 StateMixin

案例

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

// ------------------ 1. 创建 GetConnect API --------------------

class PostApi extends GetConnect {
  @override
  void onInit() {
    httpClient.baseUrl = "https://jsonplaceholder.typicode.com";
    super.onInit();
  }

  Future<Response> getPosts() => get("/posts");
}

// -------------------2. 使用 SuperController -------------------

/// SuperController<List<dynamic>>:
///   ① 管理状态(loading/success/empty/error)
///   ② 内置 refresh、生命周期方法
class PostController extends SuperController<List<dynamic>> {
  final api = Get.find<PostApi>();

  /// 拉取数据
  Future<void> fetchPosts() async {
    change(null, status: RxStatus.loading()); // 设置加载状态

    try {
      final response = await api.getPosts();
      if (response.statusCode == 200) {
        final data = response.body;
        if (data.isEmpty) {
          change([], status: RxStatus.empty());
        } else {
          change(data, status: RxStatus.success());
        }
      } else {
        change(null, status: RxStatus.error("请求失败: ${response.statusCode}"));
      }
    } catch (e) {
      change(null, status: RxStatus.error(e.toString()));
    }
  }

  @override
  void onDetached() {}
  @override
  void onInactive() {}
  @override
  void onPaused() {}
  @override
  void onResumed() {}

  @override
  void onHidden() {
    // TODO: implement onHidden
  }
}

// -----------------------3. 创建 Binding -----------------------

class PostBinding extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut<PostApi>(() => PostApi());
    Get.lazyPut<PostController>(() => PostController());
  }
}

// -----------------------4. 创建页面 ---------------------------

class PostPage extends StatelessWidget {
  PostPage({super.key});

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("GetConnect + SuperController 示例")),
      body: Column(
        children: [
          ElevatedButton(
            onPressed: () {
              controller.fetchPosts(); // 手动触发请求
            },
            child: Text("加载数据"),
          ),
          Expanded(
            child: controller.obx(
              (state) => ListView.builder(
                itemCount: state!.length,
                itemBuilder: (context, index) {
                  final post = state[index];
                  return ListTile(
                    title: Text(post["title"]),
                    subtitle: Text(post["body"]),
                  );
                },
              ),
              onLoading: Center(child: CircularProgressIndicator()),
              onEmpty: Center(child: Text("暂无数据")),
              onError: (err) => Center(child: Text("错误: $err")),
            ),
          ),
        ],
      ),
    );
  }
}

// -----------------------5. 路由配置 ---------------------------

void main() {
  runApp(
    GetMaterialApp(
      initialRoute: '/posts',
      getPages: [
        GetPage(name: '/posts', page: () => PostPage(), binding: PostBinding()),
      ],
    ),
  );
}

StateMixinSuperController

其实 StateMixinSuperController 的核心用途几乎一样:

特性 StateMixin SuperController
基础类 GetxController + StateMixin<T> 继承 SuperController<T>
状态管理 ✅ 有 RxStatus ✅ 有 RxStatus
生命周期 只有 onInit/onClose 支持 App/Widget 可见性全生命周期
是否强制实现生命周期方法 ❌ 不强制 ✅ 必须实现 (哪怕留空)
适合场景 普通页面,数据请求 更复杂的场景,需要感知 前后台切换组件隐藏显示
  • 只需要加载数据、展示数据 → 用 StateMixin 就够了(代码更简洁)。
  • 需要额外处理「前后台、暂停恢复」的逻辑 → 用 SuperController 更合适。

SuperController的生命周期

方法 触发时机 典型用途
onInit() 控制器 创建时 调用(只执行一次) 初始化数据、发起首次网络请求、订阅监听
onDetached() 组件与 widget 树 完全分离 时调用 清理资源,释放内存
onInactive() 组件处于 非活动状态,但仍在 widget 树中 暂停动画、暂停计时器
onPaused() 组件被覆盖,不可见 但仍存在 停止耗时操作(视频、网络轮询)
onResumed() 组件重新可见、恢复交互 重新拉取数据、恢复动画
onHidden() 组件 部分隐藏 时触发 可以选择性地减少刷新频率
onClose() 控制器 销毁时 调用(生命周期最后一步) 释放控制器内的资源、取消订阅、关闭流

除了onInitonClose之外,其余5个都是必须实现的方法。这是因为 SuperController 继承自 SuperLifecycle,而 SuperLifecycle 是一个 抽象类 (abstract class),里面定义了这些 生命周期方法,并且它们是 abstract 方法,没有默认实现。之所以强制实现这些方法是为了让Controller能够接收 Widget 的可见性/生命周期变化SuperController 不只是管理数据,还可以感知页面或组件的可见性状态,这样方便做 资源管理 / 数据刷新 / 自动暂停任务 等。

在很多时候我们只需要 onInit / onClose 就够了。但 SuperController 适合那些需要对 App 前后台切换页面可见性 做精细管理的场景,比如:

  • 视频播放列表 → 用户切换出去时自动 pause(),回来时 resume()
  • 聊天应用 → 页面不可见时停止轮询,回来时再拉新消息
  • 股票行情 → 切后台就不更新 UI,切回来恢复请求

生命周期图

flowchart TD

    A["onInit() 
控制器创建时调用"] --> B["onReady()
UI首次渲染完成"] B --> C["onResumed()
恢复活跃/前台"] C --> D["onPaused()
进入后台/失去活跃"] D --> E["onInactive()
非活动状态,等待用户操作"] E --> F["onHidden()
页面被部分遮挡"] F --> G["onDetached()
完全分离,不再可见"] G --> H["onClose()
控制器销毁,清理资源"] %% 状态切换说明 C -.-> D D -.-> C D -.-> E E -.-> F F -.-> C %% 样式分组 style A fill:#d9f1ff,stroke:#0366d6,stroke-width:2px style B fill:#d9f1ff,stroke:#0366d6,stroke-width:2px style C fill:#e2ffe2,stroke:#228B22,stroke-width:2px style D fill:#fffacc,stroke:#d6a600,stroke-width:2px style E fill:#fffacc,stroke:#d6a600,stroke-width:2px style F fill:#fffacc,stroke:#d6a600,stroke-width:2px style G fill:#ffe0e0,stroke:#d63333,stroke-width:2px style H fill:#ffe0e0,stroke:#d63333,stroke-width:2px

×

喜欢就点赞,疼爱就打赏