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

如何在Flutter中基于ID从MQTT Broker获取并展示特定数据?

实现方案

1. 关于write函数的说明

不需要用write函数,write是MQTT客户端用来发布消息到Broker的方法,你当前场景是订阅接收数据,只需要处理订阅后的数据流即可。

2. 具体实现步骤

步骤1:定义数据模型

先把MQTT收到的消息解析成带ID的实体类,方便后续筛选和展示:

import 'dart:convert';
import 'package:mqtt_client/mqtt_client.dart';

class DeviceData {
  final String id;
  final String value; // 可根据实际数据类型调整为int、double等

  DeviceData({required this.id, required this.value});

  // 从MQTT消息负载解析成DeviceData对象
  static DeviceData? fromMqttMessage(MqttReceivedMessage<MqttMessage> message) {
    final payload = MqttPublishPayload.bytesToStringAsString(
        (message.payload as MqttPublishMessage).payload.message);
    // 假设消息格式为JSON:{"id": "sensor_01", "value": "26.3"}
    try {
      final jsonData = jsonDecode(payload);
      return DeviceData(
        id: jsonData['id'],
        value: jsonData['value'].toString(),
      );
    } catch (e) {
      print('消息解析失败: $e');
      return null;
    }
  }
}

步骤2:在页面中处理MQTT数据流并维护状态

用StatefulWidget管理订阅和数据状态,监听MQTT的updates流,过滤出你需要的特定ID数据:

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

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

  @override
  State<MqttCardPage> createState() => _MqttCardPageState();
}

class _MqttCardPageState extends State<MqttCardPage> {
  StreamSubscription? _mqttSubscription;
  DeviceData? _targetDeviceData;
  final String _targetId = 'sensor_01'; // 你要展示的目标设备ID

  @override
  void initState() {
    super.initState();
    _startMqttSubscription();
  }

  Future<void> _startMqttSubscription() async {
    // 调用你已实现的mqttSubscribe方法订阅主题
    final updatesStream = await mqttSubscribe(topic: 'your/device/topic');
    if (updatesStream != null) {
      _mqttSubscription = updatesStream.listen((List<MqttReceivedMessage<MqttMessage>> messages) {
        for (final message in messages) {
          final deviceData = DeviceData.fromMqttMessage(message);
          // 筛选出目标ID的数据并更新UI
          if (deviceData != null && deviceData.id == _targetId) {
            setState(() {
              _targetDeviceData = deviceData;
            });
          }
        }
      });
    }
  }

  @override
  void dispose() {
    _mqttSubscription?.cancel();
    client.disconnect(); // 页面销毁时断开MQTT连接
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('设备数据展示')),
      body: Center(
        child: _targetDeviceData != null
            ? Card(
                elevation: 4,
                margin: const EdgeInsets.symmetric(horizontal: 16),
                child: Padding(
                  padding: const EdgeInsets.all(16),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Text(
                        '设备ID: ${_targetDeviceData!.id}',
                        style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                      ),
                      const SizedBox(height: 12),
                      Text(
                        '当前数值: ${_targetDeviceData!.value}',
                        style: const TextStyle(fontSize: 16),
                      ),
                    ],
                  ),
                ),
              )
            : const Text('等待数据推送...'),
      ),
    );
  }
}

步骤3:扩展支持多个特定ID的情况

如果需要展示多个设备的数据,可以用Map存储多个ID对应的数据,再遍历生成Card:

// 替换状态变量
Map<String, DeviceData> _deviceDataMap = {};
final List<String> _targetIds = ['sensor_01', 'sensor_02', 'sensor_03'];

// 监听流时更新Map
_mqttSubscription = updatesStream.listen((messages) {
  for (final message in messages) {
    final deviceData = DeviceData.fromMqttMessage(message);
    if (deviceData != null && _targetIds.contains(deviceData.id)) {
      setState(() {
        _deviceDataMap[deviceData.id] = deviceData;
      });
    }
  }
});

// 构建UI时生成多个Card
@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: const Text('多设备数据展示')),
    body: ListView.builder(
      padding: const EdgeInsets.all(16),
      itemCount: _targetIds.length,
      itemBuilder: (context, index) {
        final id = _targetIds[index];
        final data = _deviceDataMap[id];
        return Card(
          elevation: 4,
          margin: const EdgeInsets.only(bottom: 12),
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Text('设备ID: $id', style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
                const SizedBox(height: 12),
                Text(data != null ? '当前数值: ${data.value}' : '暂无数据', style: const TextStyle(fontSize: 16)),
              ],
            ),
          ),
        );
      },
    ),
  );
}

3. 注意事项

  • 确保MQTT消息格式可解析,如果不是JSON格式,调整fromMqttMessage里的解析逻辑即可。
  • 页面销毁时必须取消流订阅并断开MQTT连接,避免内存泄漏。
  • 如果需要跨页面共享数据,可结合Provider、Riverpod等状态管理库优化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 05:30:58