You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中API定时调用与按钮状态控制的代码错误排查

Flutter定时API调用与按钮状态控制问题修复

问题背景

页面初始化时通过initState调用数据获取方法,并用Timer.periodic每15秒重复执行,目标是根据API返回的doctor_in布尔值:

  • 若为false,持续调用API
  • 若为true,启用页面上的ElevatedButton
    当前代码出现编译错误:The body might complete normally, causing 'null' to be returned, but the return type...

错误原因分析

  1. 方法定义混淆:错误地将数据获取方法声明为返回FutureBuilder<DataDoctor>,但FutureBuilder是UI组件,并非数据请求方法,且方法体无返回值,导致类型不匹配。
  2. 模型类字段冲突:构造函数声明的非空字段(String、bool),在fromJson中可能返回null,违反Dart非空约束。
  3. 定时器逻辑缺失:未处理doctor_in为true时的定时器取消逻辑,会产生无效重复请求。
  4. 状态管理缺失:无按钮状态变量,无法根据API结果更新UI。

修正后的完整代码

页面状态类

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

class DoctorStatusPage extends StatefulWidget {
  const DoctorStatusPage({super.key});

  @override
  State<DoctorStatusPage> createState() => _DoctorStatusPageState();
}

class _DoctorStatusPageState extends State<DoctorStatusPage> {
  Timer? _timer;
  bool _isButtonEnabled = false;
  final ApiServiceDataDoctor _apiService = ApiServiceDataDoctor();

  @override
  void initState() {
    super.initState();
    // 初始化立即请求一次
    _fetchDoctorStatus();
    // 设置15秒定时重复请求
    _timer = Timer.periodic(const Duration(seconds: 15), (timer) {
      _fetchDoctorStatus();
    });
  }

  Future<void> _fetchDoctorStatus() async {
    try {
      List<DataDoctor> dataList = await _apiService.isDoctorActive();
      if (dataList.isNotEmpty) {
        DataDoctor doctorData = dataList.first;
        setState(() {
          _isButtonEnabled = doctorData.doctor_in;
        });
        // 医生在线时取消定时器,停止重复请求
        if (doctorData.doctor_in) {
          _timer?.cancel();
        }
      }
    } catch (e) {
      debugPrint('获取医生状态失败: $e');
    }
  }

  @override
  void dispose() {
    // 页面销毁时清理定时器
    _timer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('医生状态监控')),
      body: Center(
        child: ElevatedButton(
          onPressed: _isButtonEnabled ? () {
            // 按钮启用后的业务逻辑
          } : null,
          child: const Text('开始咨询'),
        ),
      ),
    );
  }
}

修正后的DataDoctor模型类

class DataDoctor {
  String? channelName;
  String? receiver_name;
  bool doctor_in;

  DataDoctor({
    this.channelName,
    this.receiver_name,
    required this.doctor_in,
  });

  factory DataDoctor.fromJson(Map<String, dynamic> json) {
    return DataDoctor(
      channelName: json['Mobile'],
      receiver_name: json['Name'],
      doctor_in: json['Boolean'] ?? false, // 空值时默认设为false,避免非空错误
    );
  }
}

修正后的API调用类

class ApiServiceDataDoctor {
  final String url = 'https://tools.learningcontainer.com/sample-json-file.json';
  
  Future<List<DataDoctor>> isDoctorActive() async {
    final response = await http.get(Uri.parse(url));
    if (response.statusCode == 200) {
      final Map<String, dynamic> json = jsonDecode(response.body);
      // 注意:需根据实际API返回结构调整'dataActive'字段
      final Map<String, dynamic> body = json['dataActive'] ?? {};
      return [DataDoctor.fromJson(body)];
    } else {
      throw Exception('无法获取数据,状态码: ${response.statusCode}');
    }
  }
}

关键修复点

  • 将数据获取逻辑与UI组件分离,_fetchDoctorStatus专注于请求数据和更新状态
  • 修正模型类字段可空性,给doctor_in设置默认值避免空指针
  • 添加_isButtonEnabled变量控制按钮状态,通过setState触发UI更新
  • 医生在线时自动取消定时器,停止无效重复请求
  • 在dispose中清理定时器,避免内存泄漏

内容的提问来源于stack exchange,提问作者Dasun Dola

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 05:56:05