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

Flutter中StreamBuilder结合HTTP请求使用无法更新数据问题求助

问题根因与修复方案

核心问题

你当前实现的Stream仅会发射1次数据就进入终止状态,没有持续拉取接口更新数据的逻辑,同时StreamBuilder的状态处理逻辑存在错误。

具体问题点

  • Stream生成器listMarkers仅执行1次接口请求就结束,无定时拉取逻辑,无法产生新数据
  • StreamBuilder的连接状态判断逻辑错位,waiting状态无对应处理,没有错误捕获逻辑,接口请求失败会直接崩溃
  • 接口请求方法依赖外部全局列表,存在并发修改风险
  • 每次页面重绘都会重新创建新的Stream实例,造成资源浪费

修复代码

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner:false,
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({ Key? key }) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late Stream<List<Coordonnees>> _markerStream;

  @override
  void initState() {
    super.initState();
    _markerStream = listMarkers;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: StreamBuilder(
        stream: _markerStream,
        builder: (BuildContext context,AsyncSnapshot<List<Coordonnees>> snapshot){
          // 错误处理
          if (snapshot.hasError) {
            return Center(child: Text('加载失败: ${snapshot.error}'));
          }
          // 加载中处理
          if (!snapshot.hasData) {
            return const Center(child: CircularProgressIndicator());
          }
          // 数据加载完成渲染
          List<Coordonnees> mark = snapshot.data!;
          return Center(
            child: Text(
              'latitude: ${mark[0].latitude}',
              style: const TextStyle(fontSize: 30),
            ),
          );
        },
      ),
    );
  }

  Future<List<Coordonnees>> UpdateMarkers(String id) async{ 
    Map data = {
      'idligne': id,     
    };
    final response = await http.post(
      Uri.parse("https://www.sirius-iot.eu/Dev/ESI/qitari2021/sarah.php?lignegps"),
      body: data
    );
    Map<String,dynamic> map = json.decode(response.body);
    List<dynamic> dataa = map['lignegps'];
    List<Coordonnees> marqueurs = [];
    for(var i in dataa) {  
      Coordonnees crd = Coordonnees(
        double.parse(i['latitude']),
        double.parse(i['longitude']),
        double.parse(i['vitesse'])
      );
      marqueurs.add(crd);
    } 
    return marqueurs; 
  }

  Stream<List<Coordonnees>> get listMarkers async*{
    String id = '1';
    // 循环拉取接口,间隔5秒,可根据需求调整间隔时长
    while (true) {
      yield await UpdateMarkers(id);
      await Future.delayed(const Duration(seconds: 5));
    }
  }
}
 
class Coordonnees{
  double latitude; 
  double longitude; 
  double vitesse;
  Coordonnees(this.latitude,this.longitude,this.vitesse);
}

可选优化(推荐)

上述代码的无限循环Stream无法手动停止,页面销毁后仍会在后台发起请求,建议改用StreamController+Timer实现,在页面销毁时主动释放资源:

class _MyHomePageState extends State<MyHomePage> {
  final _markerController = StreamController<List<Coordonnees>>();
  Timer? _pullTimer;

  @override
  void initState() {
    super.initState();
    // 立即拉取首次数据
    _pullData();
    // 每隔5秒拉取一次数据
    _pullTimer = Timer.periodic(const Duration(seconds: 5), (timer) => _pullData());
  }

  Future<void> _pullData() async {
    try {
      final data = await UpdateMarkers('1');
      _markerController.add(data);
    } catch (e) {
      _markerController.addError(e);
    }
  }

  @override
  void dispose() {
    _pullTimer?.cancel();
    _markerController.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: StreamBuilder(
        stream: _markerController.stream,
        builder: (BuildContext context,AsyncSnapshot<List<Coordonnees>> snapshot){
          // 此处复用之前的builder逻辑即可
        },
      ),
    );
  }
  // 其余方法保持不变
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 06:15:01