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

Flutter中MQTT消息转JSON及解决单索引多数据仅显示最后一条问题

问题解决方案

一、解决仅显示最后一条数据的问题

核心原因是你每次只处理了消息列表的第一条,且没有保留历史消息。需要通过维护一个消息列表来存储所有收到的数据,再动态渲染所有条目。

二、解决MQTT消息转JSON的问题

使用dart:convert包的jsonDecode方法将字符串格式的payload解析为JSON对象,即可针对字段编写条件判断逻辑。

修改后的完整代码

import 'dart:convert';
import 'package:flutter/material.dart';
// 导入你的MQTT相关包

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

  @override
  State<MqttSensorPage> createState() => _MqttSensorPageState();
}

class _MqttSensorPageState extends State<MqttSensorPage> {
  // 存储所有解析后的传感器JSON数据
  final List<Map<String, dynamic>> _sensorDataList = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Flutter MQTT"),
      ),
      body: FutureBuilder(
        future: mqttSubscribe(topic: "/sensor_simulator/data"),
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (snapshot.hasError) {
            return Center(
              child: Text("连接错误: ${snapshot.error}"),
            );
          }

          if (snapshot.connectionState == ConnectionState.done) {
            return StreamBuilder(
              stream: snapshot.data,
              builder: (BuildContext context, AsyncSnapshot snapshot) {
                if (snapshot.hasError) {
                  return Center(
                    child: Text("数据流错误: ${snapshot.error}"),
                  );
                }

                if (snapshot.hasData) {
                  try {
                    final List<MqttReceivedMessage> receiveMessages = snapshot.data;
                    // 遍历所有收到的消息,而非仅取第一条
                    for (var msg in receiveMessages) {
                      final recMess = msg.payload as MqttPublishMessage;
                      String payload = MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
                      // 将字符串转为JSON对象
                      Map<String, dynamic> sensorData = jsonDecode(payload);
                      // 加入列表(可限制长度避免内存占用过高)
                      setState(() {
                        _sensorDataList.add(sensorData);
                        // 可选:只保留最近10条数据
                        if (_sensorDataList.length > 10) {
                          _sensorDataList.removeAt(0);
                        }
                      });
                    }

                    // 动态渲染所有数据条目
                    return ListView.builder(
                      padding: const EdgeInsets.all(10),
                      itemCount: _sensorDataList.length,
                      itemBuilder: (context, index) {
                        var data = _sensorDataList[index];
                        // 条件判断示例:温度超过30℃时文字变红
                        Color textColor = (data['temperature'] ?? 0) > 30 ? Colors.red : Colors.black;
                        return Card(
                          child: ListTile(
                            title: Text("温度: ${data['temperature']}°C", style: TextStyle(color: textColor)),
                            subtitle: Text("湿度: ${data['humidity']}% | 气压: ${data['pressure']}hPa"),
                          ),
                        );
                      },
                    );
                  } catch (e) {
                    return Center(child: Text("解析错误: ${e.toString()}"));
                  }
                }

                return const Center(child: CircularProgressIndicator());
              },
            );
          }

          return const Center(child: CircularProgressIndicator());
        },
      ),
    );
  }
}

关键修改说明

  1. 维护消息列表:添加_sensorDataList变量存储所有解析后的JSON数据,确保历史消息不会丢失
  2. 遍历所有消息:循环处理receiveMessages中的每一条消息,而非仅取索引0的条目
  3. JSON解析:通过jsonDecode将payload字符串转为Map对象,支持直接访问字段(如data['temperature'])
  4. 条件判断示例:根据温度值动态改变文字颜色,你可以根据需求扩展更多判断逻辑
  5. 高效列表渲染:使用ListView.builder替代固定ListView,优化长列表性能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 11:15:59