Flutter框架跨平台鸿蒙开发——EventChannel事件通道

一、EventChannel概述

EventChannel用于从原生平台向Flutter发送连续的事件流,适合传感器、定位等实时数据。
持续事件
Stream
更新
HarmonyOS
EventChannel
Flutter监听
UI展示

|| 特性 | 说明 |

|------|------|

| 单向流 | 只支持原生向Flutter发送 |

| 持续数据 | 适合实时数据流 |

| 订阅模式 | 支持订阅和取消 |

| 事件驱动 | 数据到达自动推送 |

二、事件流机制

Flutter UI Stream EventChannel 原生平台 Flutter UI Stream EventChannel 原生平台 产生事件 转发事件 onData回调 setState更新 产生新事件 转发事件 onData回调

dart 复制代码
class _Page03EventChannel extends StatefulWidget {
  const _Page03EventChannel();

  @override
  State<_Page03EventChannel> createState() => _Page03EventChannelState();
}

class _Page03EventChannelState extends State<_Page03EventChannel> {
  static const eventChannel = EventChannel('com.example.demo/sensor');
  late StreamSubscription _subscription;
  List<double> _sensorData = [];
  bool _isListening = false;

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

  void _startListening() {
    setState(() {
      _isListening = true;
      _sensorData = [];
    });

    // 模拟传感器数据流
    _subscription = Stream.periodic(const Duration(milliseconds: 200), (count) {
      return (DateTime.now().millisecond % 100) / 100.0;
    }).listen(
      (data) {
        setState(() {
          _sensorData.add(data);
          if (_sensorData.length > 50) {
            _sensorData.removeAt(0);
          }
        });
      },
      onError: (error) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('传感器错误: $error')),
        );
      },
    );
  }

  void _stopListening() {
    _subscription.cancel();
    setState(() {
      _isListening = false;
    });
  }

  @override
  void dispose() {
    _subscription.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.orange.shade50,
      padding: const EdgeInsets.all(20),
      child: Column(
        children: [
          Container(
            padding: const EdgeInsets.all(20),
            decoration: BoxDecoration(
              color: Colors.orange.shade600,
              borderRadius: BorderRadius.circular(20),
            ),
            child: const Column(
              children: [
                Icon(Icons.sensors, size: 48, color: Colors.white),
                SizedBox(height: 16),
                Text(
                  'EventChannel',
                  style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold, color: Colors.white),
                ),
                SizedBox(height: 8),
                Text('事件通道流 - 页面 3/10', style: TextStyle(color: Colors.white70)),
              ],
            ),
          ),
          const SizedBox(height: 24),
          Expanded(
            child: Container(
              padding: const EdgeInsets.all(20),
              decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(20)),
              child: Column(
                children: [
                  // 模拟传感器波形
                  Expanded(
                    child: CustomPaint(
                      painter: _WavePainter(_sensorData),
                      child: Container(),
                    ),
                  ),
                  const SizedBox(height: 20),
                  Text(
                    '当前值: ${_sensorData.isNotEmpty ? _sensorData.last.toStringAsFixed(2) : '--'}',
                    style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
                  ),
                  const SizedBox(height: 20),
                  ElevatedButton(
                    onPressed: _isListening ? _stopListening : _startListening,
                    style: ElevatedButton.styleFrom(
                      backgroundColor: _isListening ? Colors.red : Colors.orange.shade600,
                    ),
                    child: Text(
                      _isListening ? '停止监听' : '开始监听',
                      style: const TextStyle(color: Colors.white),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _WavePainter extends CustomPainter {
  final List<double> data;

  _WavePainter(this.data);

  @override
  void paint(Canvas canvas, Size size) {
    if (data.isEmpty) return;

    final paint = Paint()
      ..color = Colors.orange.shade600
      ..strokeWidth = 2
      ..style = PaintingStyle.stroke;

    final path = Path();
    final stepX = size.width / 50;
    final centerY = size.height / 2;

    for (int i = 0; i < data.length; i++) {
      final x = i * stepX;
      final y = centerY - (data[i] * centerY * 0.8);
      if (i == 0) {
        path.moveTo(x, y);
      } else {
        path.lineTo(x, y);
      }
    }

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(_WavePainter oldDelegate) {
    return data != oldDelegate.data;
  }
}

三、监听管理

操作 方法 说明
订阅 listen() 开始监听事件
取消 cancel() 停止监听
错误处理 onError 处理异常
完成 onDone 流结束回调

四、应用场景

30% 25% 20% 15% 10% 典型应用场景 传感器数据 位置定位 网络状态 蓝牙连接 其他

五、最佳实践

  • ✅ 及时取消订阅
  • ✅ 限制数据更新频率
  • ✅ 处理错误和完成事件
  • ❌ 避免内存泄漏

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

相关推荐
见山是山-见水是水3 小时前
鸿蒙Divider 分割线组件完全指南:内容分组、视觉分区与自定义样式
华为·harmonyos
贾伟康4 小时前
【知律|18】HarmonyOS ArkTS 权限与隐私实战:让 module.json5、功能说明和拒绝路径一致
harmonyos·arkts·隐私合规·appgallery·应用权限
xcyxiner14 小时前
flutter wsl2安装记录(使用宿主机虚拟机)
前端·flutter
Kevin Coding15 小时前
JsonConvert:适用于 Android、鸿蒙与 Flutter 的 JSON 转 Model 插件
android·flutter·harmonyos
m0_7496902317 小时前
【寻迹校园 HarmonyOS NEXT 实战 28】不交换手机号也能交接:固定校内交接点的隐私设计
华为·harmonyos·arkts·产品设计·隐私设计·安全交接
Magic-ZYJ17 小时前
HarmonyOS Stage 模型实战:UIAbility 生命周期如何驱动页面安全状态
安全·华为·harmonyos·鸿蒙·移动端开发·独立开发者·心晴手记
贾伟康17 小时前
【中国方言题库|09】HarmonyOS ArkTS 方言搜索实战:实现词语检索和无结果反馈
harmonyos·arkts·状态管理·arkui·本地搜索
Dovis(誓平步青云)18 小时前
从手机单栏到平板分栏:任务清单的筛选、选中态与不可变更新
华为·harmonyos
梦想不只是梦与想18 小时前
鸿蒙 AppGallery Connect:查看应用信息(三)
harmonyos·appgallery·client id·app id·developer id
贾伟康18 小时前
【中国方言题库|03】HarmonyOS ArkTS 四川话分库实战:复用题库组件并保持地区参数清晰
harmonyos·arkts·arkui·路由传参·组件复用