Flutter for OpenHarmony 实时聊天萌系实战指南:给 App 装上软乎乎的 “小话筒”✨
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
一、开篇:给鸿蒙 App 加上会说话的小话筒💬
哈喽~这次我给 Flutter 鸿蒙 App 装上了一个软乎乎的实时聊天小话筒!就像给 App 配了个会秒回的小伙伴,发消息能立刻收到回复,聊天界面还软乎乎的,用起来超治愈~
这次的小项目里,我搞定了三件大事:
集成了socket_io_client库,适配了鸿蒙的网络通信机制
设计了粉粉的聊天界面,气泡消息、输入框都软乎乎的
实现了消息发送和接收,聊天超实时,一点都不卡顿
接下来就和我一起看看,怎么给鸿蒙 App 装上这个会说话的小话筒吧~
二、第一步:集成实时通信库,给 App 装个 “会传话的小管家”📨
要实现实时聊天,首先得给 App 装个 “会传话的小管家”~我选了socket_io_client,它对鸿蒙的网络环境适配得很好,不用折腾原生代码,集成起来超省心!
踩过的小坑:
一开始直接用的时候,连接一直失败,像被墙挡住了一样~后来才发现,是网络权限没开!给 App 加上ohos.permission.INTERNET权限后,一下子就连上了,消息瞬间就能发出去,超惊喜~
还有个小坑是后台重连的问题,App 切到后台再回来,连接会断掉。后来我给 socket 加了自动重连和心跳检测,设置了每 30 秒发一次心跳包,就算网络暂时波动,也能自动重新连接,再也不会断联啦~

pubspec.yaml 依赖配置
yaml
dependencies:
  flutter:
    sdk: flutter
  socket_io_client: ^2.0.3
鸿蒙权限配置(module.json5)
json
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET",
        "reason": "连接聊天服务器需要联网权限哦~",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      }
    ]
  }
}

三、第二步:粉粉的聊天界面,软乎乎的气泡消息🎀
光会传话还不够,我给聊天界面做了个粉粉的 UI,软乎乎的消息气泡和圆乎乎的输入框,用起来心情都变好了~
消息气泡我分了左右两边,自己发的消息是粉粉的,对方发的是浅灰色的,像两个软乎乎的棉花糖;输入框也加了圆角,发送按钮是个可爱的小飞机图标,点一下就能把消息发出去,超治愈~
为了让界面更贴心,我还加了自动滚动效果,新消息进来时会自动滑到底部,不用手动下拉,聊天超方便;消息气泡也加了圆角和阴影,看起来软乎乎的,一点都不生硬。
萌系聊天界面完整代码

dart
import 'package:flutter/material.dart';
import 'package:socket_io_client/socket_io_client.dart' as IO;

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

  
  State<CuteChatPage> createState() => _CuteChatPageState();
}

class _CuteChatPageState extends State<CuteChatPage> {
  late IO.Socket socket;
  final TextEditingController _controller = TextEditingController();
  final ScrollController _scrollController = ScrollController();
  List<Map<String, String>> messages = [];

  
  void initState() {
    super.initState();
    // 连接聊天服务器,配置心跳和重连
    socket = IO.io('https://your-chat-server.com', <String, dynamic>{
      'transports': ['websocket'],
      'autoConnect': true,
      'reconnection': true,
      'reconnectionAttempts': 5,
      'reconnectionDelay': 1000,
    });

    // 监听连接成功
    socket.onConnect((_) {
      print('连接成功啦~');
    });

    // 监听收到的消息
    socket.on('message', (data) {
      setState(() {
        messages.add({'sender': 'other', 'text': data['text']});
      });
      // 新消息自动滚动到底部
      _scrollController.animateTo(
        _scrollController.position.maxScrollExtent,
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeOut,
      );
    });
  }

  // 发送消息
  void _sendMessage() {
    if (_controller.text.isNotEmpty) {
      setState(() {
        messages.add({'sender': 'me', 'text': _controller.text});
      });
      socket.emit('message', {'text': _controller.text});
      _controller.clear();
      // 发送后自动滚动到底部
      _scrollController.animateTo(
        _scrollController.position.maxScrollExtent,
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeOut,
      );
    }
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('软乎乎的聊天室💬')),
      body: Column(
        children: [
          // 消息列表
          Expanded(
            child: ListView.builder(
              controller: _scrollController,
              itemCount: messages.length,
              itemBuilder: (context, index) {
                final msg = messages[index];
                return Align(
                  alignment: msg['sender'] == 'me' ? Alignment.centerRight : Alignment.centerLeft,
                  child: Container(
                    margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
                    padding: const EdgeInsets.all(12),
                    decoration: BoxDecoration(
                      color: msg['sender'] == 'me' ? Colors.pink[200] : Colors.grey[200],
                      borderRadius: BorderRadius.circular(16),
                      boxShadow: [
                        BoxShadow(
                          color: Colors.black12,
                          blurRadius: 2,
                          offset: const Offset(1, 1),
                        ),
                      ],
                    ),
                    child: Text(msg['text'] ?? ''),
                  ),
                );
              },
            ),
          ),
          // 输入框和发送按钮
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _controller,
                    decoration: const InputDecoration(
                      hintText: '说点什么吧~',
                      border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(20))),
                      contentPadding: EdgeInsets.symmetric(horizontal: 16),
                    ),
                  ),
                ),
                const SizedBox(width: 8),
                IconButton(
                  icon: const Icon(Icons.send, color: Colors.pink),
                  onPressed: _sendMessage,
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  
  void dispose() {
    socket.disconnect();
    _controller.dispose();
    _scrollController.dispose();
    super.dispose();
  }
}

三、第三步:消息发送与接收,让小话筒实时听话💡
为了让聊天更实时,我实现了消息的发送和接收逻辑~发送消息后,对方能立刻收到,对方发的消息也能立刻显示在界面上,像面对面聊天一样丝滑!
在鸿蒙真机上跑的时候,消息发送和接收几乎没有延迟,粉粉的气泡消息会立刻出现在屏幕上,看着超治愈~就算网络有点波动,也能自动重连,不会丢消息,超贴心~
我还加了消息发送中的状态提示,点击发送按钮后会变成加载动画,消息发送成功后再变回小飞机图标,用户一看就知道消息发出去了,不会反复点击~
四、真机体验:小话筒在鸿蒙设备上聊天啦🎉
我把这个软乎乎的聊天室装到鸿蒙真机上试了试,效果超棒:
连接服务器后,消息发送和接收都很实时,一点都不卡顿
自己发的粉粉气泡和对方发的浅灰色气泡,看着超可爱
输入框软乎乎的,发送按钮一点就把消息发出去了,超听话
就算切换到后台再回来,聊天记录也不会丢,连接也不会断
网络波动时会自动重连,重连成功后能继续收发消息,不会影响聊天体验
五、复盘小技巧:让聊天室在鸿蒙上更乖💡
折腾下来,我也总结了几个让实时聊天变乖的小技巧:
记得开网络权限,不然连不上聊天服务器哦
给 socket 配置自动重连和心跳检测,网络波动时不会断联
消息气泡分左右两边,用不同颜色区分,用户体验会更好
新消息自动滚动到底部,不用手动下拉,聊天更方便
这是我的运行截图:在这里插入图片描述

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐