一块候诊叫号屏。一个大数字、一行等待人数、两个按钮。
平常做这个要什么?建工程、写控件树、构建、装到面板上。想把数字调大?这四步再走一遍。
而这里,画面就是服务端上的一个文件。 一连上,文件就来了。
画面
全部就这些。
{ "type": "page", "title": "Front Desk",
"content": { "type": "center",
"child": { "type": "linear", "direction": "vertical", "spacing": 16, "alignment": "center", "children": [
{ "type": "text", "text": "NOW SERVING", "style": { "fontSize": 18, "letterSpacing": 4, "color": "#6b7280" } },
{ "type": "text", "text": "{{now}}", "style": { "fontSize": 96, "fontWeight": "bold", "color": "#111827" } },
{ "type": "text", "text": "{{waiting}} waiting · issued {{issued}}", "style": { "fontSize": 20, "color": "#6b7280" } },
{ "type": "linear", "direction": "horizontal", "spacing": 12, "children": [
{ "type": "button", "label": "Call next", "onTap": { "type": "tool", "tool": "queue.next" } },
{ "type": "button", "label": "Take a ticket", "onTap": { "type": "tool", "tool": "queue.take" } } ] } ] } } }
标题写的是十行,实际收在了 九行、848 字节。
数字落在 {{now}} 的位置。按钮的 onTap 叫的是工具名——这一篇里按下去还什么都不会发生。那是下一篇的事。
那九行在服务端
服务端的代码就这么多。
server.addResource(
uri: 'ui://app',
name: 'Front Desk screen',
description: 'The screen definition, served as a file',
mimeType: 'application/json',
handler: (uri, params) async => ReadResourceResult(contents: [
ResourceContentInfo(
uri: 'ui://app',
mimeType: 'application/json',
text: File(_screenPath).readAsStringSync(),
)
]),
);
每次请求都重新读文件。 启动时读一次放内存里更快,但那样一改画面就得重启服务端,而在那一刻,这个样例主张的事——改了文件就是另一个应用——就成了假的。
/// Read fresh on every request, deliberately. A screen cached at boot is a
/// screen you have to restart the server to change, and then the thing this
/// sample claims — edit the file, get a new app — stops being true.