Flutter Consul服务集成插件dart_consul的使用
Flutter Consul服务集成插件dart_consul的使用
什么是dart_consul?
dart_consul
是一个用于在终端或命令行界面中创建桌面窗口系统的简单、有限、初级且奇怪的项目。目前仅在我的一台Linux机器上测试过,可能不会在Windows或macOS上正常工作。如果您愿意,可以进行测试并反馈结果。
该项目使用Dart语言编写,因为我在学习Dart以进入Flutter(和Flutter Flame)领域。也许吧,我们拭目以待。
示例截图
以下是 example.dart
运行时的截图:
依赖项
除了一些显而易见的Dart依赖项外,此项目还使用了以下依赖项:
- termlib 用于终端交互
- console 用于通过Braille Unicode字符块绘制画布
- dart_console 通过一些本地代码提供原始终端访问
- rxdart 用于实现“throttleTime”,这样我就不用自己实现了
- ansi 用于ANSI样式
没有这些依赖项,这个有趣的小项目将无法存在!
它能工作吗?
嗯,在我的机器上它能工作…… 😂
您可以尝试包含的 example.dart
并自行查看。
基本想法如下:
final desktop = Desktop(...);
desktop.onKey('k', () => doSomething());
final window = Window(
"some-id",
"Some Title",
size: WindowSize.defaultMinMax(Size(60, 40)),
position: RelativePosition.fromTopLeft(xOffset: 4, yOffset: 2),
redraw: () => "Hello, world!",
);
desktop.openWindow(window);
它支持基于“Braille”字符的“画布”。这使得您可以像在 example.dart
中一样做些事情。
注意,这种画布功能来自 console。
示例动画GIF:
这里有一个快速拼凑的游戏框架更新:
待办事项
对于“版本1”的必备功能:
- 基本对话系统
- 基本弹出系统
其他考虑事项:
- 可能的任务栏显示所有窗口(包括最小化)
- 可能的任务栏溢出显示剩余窗口
- 可能的活动窗口标题闪烁(或以其他方式指示,特别是小窗口)
- 可能的菜单栏系统
- 可能的改进终端调整大小处理
- 可能的使用包含依赖项的表格/边框功能
- 可能使滚动视图、边框视图等成为透明使用的第一个类概念
已完成
- 绘制窗口
- 窗口标题栏及控制
- 控制台输入处理(目前仅限按键)
- 切换标签
- 控制台鼠标输入处理
- 通过按键最小化/最大化/关闭窗口
- 嵌套按键处理
- 通过按键移动窗口
- 通过按键调整窗口大小
- 窗口钩子(状态和大小)
- 基本鼠标操作(提升、最小化、最大化、关闭)
- 通过鼠标调整窗口大小
- 通过鼠标移动窗口
- 添加帮助按钮以显示按键配置
- 添加基本(仅垂直)滚动内容
Bug
- 重大 快速移动窗口,然后移动另一个窗口会导致第一个窗口再次移动。
- 重大 聚焦时未正确跳过最小化的窗口。
已修复的Bug
- 关键 调整大小控件的一个偏移错误。似乎只适用于某些
Position
类型? - 重大 标题栏控件不尊重窗口标志。
- 移动覆盖在窗口太小时显示。
- 在替换区域中绘制缓冲区到缓冲区会破坏ANSI。
潜在修复:收集被替换的ANSI序列,并添加到
Cell.after
的最后一个单元格。 相关:Cell.reset
应该在Cell.after
之前发生?现在看起来更有意义。 - 与前一个相关的:ANSI序列泄漏到绘制的部分。
- 当窗口向左移动时破坏ANSI。 潜在修复:收集所有剪切掉的ANSI序列并组合成一个。 放置在第一个可见单元格中。
示例代码
以下是 example.dart
的完整示例代码:
import 'dart:async';
import 'dart:io';
import 'package:dart_consul/dart_consul.dart';
import 'package:dart_minilog/dart_minilog.dart';
import 'src/demo_keys.dart';
import 'src/gol.dart';
import 'src/starfield.dart';
void main(List<String> args) async {
final conIO = TermLibConIO();
try {
await createDesktop(conIO);
} finally {
conIO.close();
}
exit(0); // 强制退出带有运行定时器等
}
Future createDesktop(ConIO conIO) async {
final desktop = Desktop(conIO: conIO);
notify(it) => desktop.sendMessage(it);
// 使用间接方式使菜单条目更易读。但你也可以直接在条目中使用lambda。
// 你不必使用notify/subscribe。这只是可用的一种简单的内置机制。
confirmQuit() => notify("quit");
// showGameOfLife() => notify("show-gol");
// showStarfield() => notify("show-starfield");
// changeFps() => notify("change-fps");
// 注意使用"quit"作为消息来结束[Desktop.run]。
desktop.subscribe("quit", (_) => desktop.exit()); // TODO确认对话框
desktop.subscribe("show-gol", (_) => gameOfLife(desktop));
desktop.subscribe("show-starfield", (_) => starfield(desktop));
desktop.subscribe("change-fps", (_) => print("TODO"));
// desktop.interceptSigInt = true;
desktop.setDefaultKeys();
desktop.onKey("q", description: "Quit", action: confirmQuit);
gameOfLife(desktop);
starfield(desktop);
addDemoKeys(desktop);
addAnsiDemo(desktop);
final log = DebugLog(redraw: () => desktop.redraw());
addDebugLog(
desktop,
log: log,
key: "<C-w>l",
position: RelativePosition.fromBottom(yOffset: -1),
);
addAutoHelp(
desktop,
key: "<C->>",
position: RelativePosition.fromBottomRight(),
);
// 将日志输出重定向到我们的[DebugLog]:
sink = (e) => log.add(e);
logLevel = LogLevel.verbose;
logVerbose("verbose");
logDebug("debug");
logInfo("info");
logWarn("warn");
logError("error");
desktop.focusById('stars');
return await desktop.run();
}
void addAnsiDemo(Desktop desktop) {
final window = Window("ansi-demo", "ANSI Demo",
size: WindowSize.fixed(Size(20, 10)),
position: RelativePosition.autoCentered(),
redraw: () =>
"some red\n".red() +
"some blue\n".bgBlue() +
"some invers\n".inverse() +
"some bold\n".bold() +
"some italic\n".italic() +
"some underline\n".underline() +
"some dim\n".dim() +
"some strike-through\n".strikeThrough());
window.onKey(
"q",
description: "Close window",
action: () => desktop.closeWindow(window),
);
desktop.openWindow(window);
}
更多关于Flutter Consul服务集成插件dart_consul的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter Consul服务集成插件dart_consul的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中集成并使用dart_consul
插件来与Consul服务进行交互的示例代码。这个示例将展示如何连接到Consul服务器、注册服务和查询服务。
首先,确保你已经在pubspec.yaml
文件中添加了dart_consul
依赖:
dependencies:
flutter:
sdk: flutter
dart_consul: ^x.y.z # 替换为最新版本号
然后运行flutter pub get
来获取依赖。
接下来,在你的Flutter项目中,你可以使用以下代码来与Consul进行交互:
import 'package:flutter/material.dart';
import 'package:dart_consul/dart_consul.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Consul Integration'),
),
body: ConsulIntegrationExample(),
),
);
}
}
class ConsulIntegrationExample extends StatefulWidget {
@override
_ConsulIntegrationExampleState createState() => _ConsulIntegrationExampleState();
}
class _ConsulIntegrationExampleState extends State<ConsulIntegrationExample> {
String result = '';
@override
void initState() {
super.initState();
_connectToConsul();
}
Future<void> _connectToConsul() async {
try {
// 配置Consul客户端
var consulClient = ConsulClient(
scheme: 'http', // 或者 'https'
host: 'localhost',
port: 8500,
);
// 注册服务
var registration = ServiceRegistration(
id: 'my-flutter-app',
name: 'my-flutter-service',
address: '127.0.0.1',
port: 8080,
tags: ['web'],
check: HttpCheck(
path: '/health',
interval: '10s',
),
);
await consulClient.agent.service.register(registration);
print('Service registered successfully');
// 查询服务
var services = await consulClient.health.service(service: 'my-flutter-service');
setState(() {
result = services.map((service) => service.service.name).join(', ');
});
} catch (e) {
print('Error: $e');
setState(() {
result = 'Error: $e';
});
}
}
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Consul Integration Result:'),
Text(result),
],
),
);
}
}
注意事项
- Consul Server: 确保你的Consul服务器正在运行,并且可以通过你提供的
host
和port
访问。 - 服务地址和端口: 在
ServiceRegistration
中,确保address
和port
是运行Flutter应用的服务器的实际地址和端口。 - 健康检查路径: 在
HttpCheck
中,path
应该是一个有效的健康检查路径,该路径应该在你的Flutter应用中实现并返回HTTP 200状态码。
运行
将上述代码添加到你的Flutter项目中,并运行应用。你应该会看到应用与Consul服务器进行交互的结果,包括服务注册和查询服务的输出。
这个示例代码展示了如何使用dart_consul
插件进行基本的Consul集成。根据你的具体需求,你可能需要调整代码以处理更多的Consul功能。