几周前,我为自己打开了Flutter。 它极大地改变了移动应用程序的开发。 我现在称呼它为“愉快的发展”。
我们将在本文中实现以下方案:
- DAZN,请在流媒体中分享abbonarsi e vedere le partite
- 流媒体方面的5大挑战; 雷·戴维斯 数字音频播放器; 流数据
- Netflix vs Amazon Prime Video:谁在新兴市场中获胜?
- 《宇宙通报》 — 9
- 节奏的Pirataria em tempos
- 移动聊天应用程序允许用户编写文本消息,然后将消息发送到服务器,并异步接收来自服务器的回声答案。 移动聊天应用程序是使用Dart lang和Flutter框架开发的。
- 聊天回声服务器是使用Go语言开发的。 它通过简单的gRPC Send方法从客户端接收消息。 服务器通过gRPC服务器端流传输方法Subscribe向客户端重播回显。
- 我们将使用protobuf定义用于客户端-服务器通信的API。
这是我们的Flutter聊天客户端应用程序的外观:
您可以在此处获得本文的完整源代码:
amsokol / flutter-grpc-tutorial
通过在GitHub上创建一个帐户,为amsokol / flutter-grpc-tutorial开发做出贡献。 github.com
先决条件
- 开始之前,我们必须已安装并配置Go v1.11 +。 我们将使用Go模块的功能。
- 我们必须安装Dart 2的Server SDK。尽管Flutter包含Dart SDK,我们仍需要独立安装才能根据protobuf API定义生成Dart文件。
- 我们必须安装Flutter v1.0 +。
- 我们必须安装protobuf编译器。 在此处查看详细信息。
- 接下来为Proto编译器安装Go代码生成器插件:
去获取-u github.com/golang/protobuf/protoc-gen-go
- 最后一步是为Dart安装protoc插件:
pub global activate protoc_plugin
项目骨架
我们将使用以下项目结构:
flutter-grpc-tutorial ( 根文件夹 )
|
| ----- api ( 原始API定义 )
| ----- flutter_client ( 聊天客户端应用程序 )
| ----- 转到服务器 ( 回显聊天服务器 )
| ----- third_party ( 需要其他文件才能从原始协议编译Go和Dart文件 )
第三方档案
我们需要从此处将empty.proto , timestamp.proto和wrappers.proto下载到flutter-grpc-tutorial / third_party / google / protobuf文件夹。
注意:文件protoc-gen.cmd是可选的-不用管它。 它是Windows原型编译脚本的示例。
定义客户端-服务器通信API
api部分仅包含一个具有ChatService定义的文件:
聊天服务器
第一步是根据proto API定义生成Go protobuf / grpc代码。 我们必须先创建输出文件夹:
cd flutter-grpc-tutorial
mkdir -p go-server / pkg / api / v1
然后生成Go代码:
protoc chat.proto --proto_path = api / proto / v1 --proto_path =。 --go_out = plugins = grpc:go-server / pkg / api / v1
代码生成的结果应如下所示:
接下来,我们必须创建go-server / pkg / service / v1 / chat.go文件-ChatService实现。 服务器从客户端接收消息并将其存储到通道。 Subscribe方法从通道获取消息,并将回显发送回客户端。 实现非常简单:
请在此处获取go-server的完整源代码。
创建Flutter客户端应用程序项目
我已将此官方教程用作Flutter客户端的入门文章:
用Flutter构建漂亮的UI
Flutter拥有丰富的Material Design和Cupertino(iOS),可轻松开始构建精美的应用程序… codelabs.developers.google.com
我强烈建议您学习本课。 它可以帮助您了解如何使用Flutter开发出色的UI应用程序。
注意1:为了使代码简单,我避免执行“针对iOS和Android定制”步骤。
注意2:我将main.dart文件拆分为多个文件。 我更喜欢几个小代码文件,而不是一个大文件。
您可以在此处获取我们Flutter客户端应用程序的源代码。
在开始之前,让我们打开pubspec.yaml文件以查看我们正在使用的Dart程序包。 这是依赖项部分:
grpc和protobuf软件包为Dart语言提供了gRPC引擎。 uuid用于为聊天消息生成唯一的ID。
第一步是根据proto API定义生成Dart protobuf / grpc代码。 我们必须先创建输出文件夹:
cd flutter-grpc-tutorial
mkdir -p flutter_client / lib / api / v1 / google / protobuf
然后,为protobuf支持文件和chat.proto生成Dart代码:
protoc empty.proto timestamp.proto wrappers.proto --proto_path = third_party / google / protobuf --plugin = protoc-gen-dart =%USERPROFILE%/ AppData / Roaming / Pub / Cache / bin / protoc-gen-dart.bat --dart_out = grpc:flutter_client / lib / api / v1 / google / protobuf
protoc chat.proto --proto_path = api / proto / v1 --proto_path = third_party --plugin = protoc-gen-dart =%USERPROFILE%/ AppData / Roaming / Pub / Cache / bin / protoc-gen-dart.bat- -dart_out = grpc:flutter_client / lib / api / v1
注意:仅Windows需要参数plugin = protoc-gen-dart =%USERPROFILE%/ AppData / Roaming / Pub / Cache / bin / protoc-gen-dart.bat 。 对于MacOS和Linux,请忽略此选项。
生成的结果应如下所示:
大。 让我们看一下其他Dart文件:
主镖
然后,它使用从原型文件ChatServiceClient存根生成的消息发送到服务器。 如果成功,它将引发onSentSuccess事件,消息事件状态已更新(从UNKNOWN到SENT ):
如果发生错误,它将引发onSentError事件,使客户端连接无效并尝试再次发送。 当应用程序关闭时,它将停止尝试发送消息:
接下来看一下startListening方法。 它还创建到服务器的客户端连接通道:
然后,它使用从原始文件ChatServiceClient存根生成的gRPC流打开,并开始侦听传入的消息。 当消息到达时,它将引发onReceivedSuccess事件:
如果发生错误或关闭流,则会引发onReceivedError事件,使客户端连接无效,尝试再次打开并侦听流。 当应用程序关闭时,它将停止尝试监听传入的消息:
chat_screen.dart
键入消息文本并按“发送”按钮时,将引发_handleSubmitted事件。 它根据输入文本创建新的传出消息,通过带宽缓冲区显示该消息并将消息发送到服务器。 发送消息是异步操作,因此我们目前不知道结果:
这是我们处理聊天客户端服务事件的方式。 这是非常简单的代码:
接下来, 构建方法的一部分演示了我们如何在移动设备屏幕上显示消息:
我们使用功能强大的StreamBuilder类通过从多个来源向流发送数据来显示聊天消息。 源是事件处理程序_handleSubmitted,onSentSuccess,onReceivedSuccess。
_addMessages方法更新现有外发消息的状态,或将新的外发或传入消息添加到消息列表:
然后,ListView构建器使用结果消息列表中的消息创建ListView小部件:
因此,我们只剩下一个重要的话题-带宽缓冲区。 看一下我在Flutter GitHub存储库中创建的问题:
StreamBuilder删除一些使用StreamController添加的值·问题#26375·颤振/颤振
嗨,非常感谢Flutter! 代码:import’dart:async’; 导入’package:flutter / material.dart’; void main()=>… github.com
感谢Flutter团队的zoechi的回答。 根据他的建议,我尝试使用stream_transform Dart包中的debounceBuffer。 不幸的是,它对我不起作用。 这就是为什么我开发了简单的BandwidthBuffer类。 它会累积消息,并在您在类构造函数中指定的时间段内将消息发送给StreamBuilder不超过一次。
此代码使用500毫秒持续时间参数创建缓冲区:
这是将消息发送到缓冲区的方法:
此事件每500毫秒引发一次,以通过StreamController对象将消息发送到StreamBuilder:
这是width_buffer.dart的代码:
让我们向服务器发送几条消息:
有用!
但这还没有结束。 我们的Flutter聊天应用程序具有一定的容错能力。 它可以在离线模式下工作。 为确保这一点,请关闭服务器并再次键入消息:
看,我们的消息被标记为发送。 然后再次启动服务器,您将看到发生了什么。 在Dart gRPC客户端重新连接到服务器之前,可能要花费一些时间:
目前为止就这样了。 完整的源代码在这里。
谢谢!