如何用GetX管理页面并自定义API请求触发时机?
用GetX改造Flutter页面API请求逻辑,解决重复请求问题
原来在initState中初始化API请求和定时任务,每次进入页面都会重复创建定时器、发送请求。现在通过GetX实现以下需求:
- 应用首次启动时按需触发请求
- 自定义
kriptoGetir和haberGetir的调用间隔 - 避免页面重复进入时重复创建定时任务
1. 创建GetX控制器类
新建控制器类,把状态管理、API请求、定时逻辑统一移到这里,利用GetX的生命周期和可观察状态替代原有的setState:
import 'package:get/get.dart'; import 'package:http/http.dart' as http; import 'package:xml2json/xml2json.dart'; import 'dart:convert'; import 'dart:async'; class KriptoHaberController extends GetxController { // 可观察列表,状态变化自动通知UI更新 final RxList<KriptoModel> kriptoList = <KriptoModel>[].obs; final RxList<Haber> haberList = <Haber>[].obs; final RxList<List<double>> sparklineList = <List<double>>[].obs; // 定时器实例,用于页面销毁时取消 Timer? _kriptoTimer; Timer? _haberTimer; // 替换为你的实际API地址 final String url = "你的加密货币API地址"; final String haberUrl = "你的新闻API地址"; @override void onInit() { super.onInit(); // 首次启动触发初始请求 _loadInitialData(); // 设置定时任务 _setupTimers(); } @override void onClose() { // 页面销毁时取消定时器,防止内存泄漏 _kriptoTimer?.cancel(); _haberTimer?.cancel(); super.onClose(); } // 加载初始数据 void _loadInitialData() async { await kriptoGetir(); await haberGetir(); } // 配置定时任务,自定义调用间隔 void _setupTimers() { // 加密货币每45秒请求一次 _kriptoTimer = Timer.periodic(const Duration(seconds: 45), (_) => kriptoGetir()); // 新闻每260秒请求一次 _haberTimer = Timer.periodic(const Duration(seconds: 260), (_) => haberGetir()); } // 重构后的加密货币API请求 Future<List<KriptoModel>> kriptoGetir() async { kriptoList.clear(); sparklineList.clear(); final response = await http.get(Uri.parse(url)); if (response.statusCode == 200) { final List<dynamic> jsonRes = json.decode(response.body); for (var item in jsonRes) { if (item != null) { final kripto = KriptoModel.fromJson(item); kriptoList.add(kripto); sparklineList.add(item['sparkline_in_7d']['price'].cast<double>()); } } print('加密货币请求发送成功'); return kriptoList.toList(); } else { throw Exception('加密货币请求失败'); } } // 重构后的新闻API请求 Future<List<Haber>> haberGetir() async { haberList.clear(); final Xml2Json xml2json = Xml2Json(); final res = await http.get(Uri.parse(haberUrl)); if (res.statusCode == 200) { xml2json.parse(res.body); final jsonString = xml2json.toParker(); final jsonRes = jsonDecode(jsonString); final List jsonLs = jsonRes['haberler']['haber'] as List; haberList.assignAll(jsonLs.map((e) => Haber.fromJson(e)).toList()); print('新闻请求发送成功'); return haberList.toList(); } else { throw Exception('新闻请求失败'); } } }
2. 修改页面代码,接入GetX控制器
将原StatefulWidget改为StatelessWidget(GetX推荐无状态组件),通过Obx监听状态变化:
import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'your_controller_path.dart'; // 替换为你的控制器文件路径 class KriptoHaberPage extends StatelessWidget { // 初始化控制器,GetX自动管理其生命周期 final KriptoHaberController controller = Get.put(KriptoHaberController()); KriptoHaberPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('加密货币与新闻')), body: Column( children: [ // 加密货币列表区域 Expanded( child: Obx(() { if (controller.kriptoList.isEmpty) { return const Center(child: CircularProgressIndicator()); } return ListView.builder( itemCount: controller.kriptoList.length, itemBuilder: (context, index) { final kripto = controller.kriptoList[index]; return ListTile(title: Text(kripto.name)); // 替换为你的自定义UI }, ); }), ), // 新闻列表区域 Expanded( child: Obx(() { if (controller.haberList.isEmpty) { return const Center(child: CircularProgressIndicator()); } return ListView.builder( itemCount: controller.haberList.length, itemBuilder: (context, index) { final haber = controller.haberList[index]; return ListTile(title: Text(haber.title)); // 替换为你的自定义UI }, ); }), ), ], ), ); } }
关键改造说明
- 状态响应:用
RxList替代普通列表,状态变化自动触发UI更新,彻底抛弃setState - 定时任务唯一性:定时器在控制器
onInit中创建,仅初始化一次,避免页面重复进入时重复创建 - 内存泄漏防护:在控制器
onClose中取消定时器,确保页面销毁时释放资源 - 按需触发:若需手动触发请求(如下拉刷新),直接调用
controller.kriptoGetir()即可
内容的提问来源于stack exchange,提问作者Yusuf Barulay
相关产品推荐
相关产品推荐

