flutter-duit-bdui by madteacher/mad-agents-skills
npx skills add https://github.com/madteacher/mad-agents-skills --skill flutter-duit-bduiDuit 实现了 Flutter 应用中的后端驱动 UI。服务器通过 JSON 控制数据和布局,允许在不发布应用的情况下更新 UI。
- Dart SDK: >=3.4.4 <4.0.0
- Flutter: >=3.24.0
flutter pub add flutter_duit
安装:
flutter pub get
import 'package:flutter/material.dart';
import 'package:flutter_duit/flutter_duit.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: DuitViewHost.withDriver(
driver: XDriver.static({
"type": "Text",
"id": "1",
"attributes": {"data": "Hello, World!"},
}),
),
),
);
}
}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
始终释放驱动以防止内存泄漏:
class MyWidgetState extends State<MyWidget> {
late final XDriver driver;
@override
void initState() {
super.initState();
driver = XDriver.static(/* ... */);
}
@override
void dispose() {
driver.dispose();
super.dispose();
}
}
从 REST API 端点获取布局:
final driver = XDriver(
transportManager: HttpTransportManager(
options: HttpTransportOptions(
baseUrl: 'https://api.example.com/view',
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
),
),
);
实时双向通信:
final driver = XDriver(
transportManager: WSTransportManager(
options: WSTransportOptions(
url: 'wss://api.example.com/ws',
headers: {
'Authorization': 'Bearer $token',
},
reconnectInterval: Duration(seconds: 5),
heartbeatInterval: Duration(seconds: 30),
),
),
);
用于测试或本地布局:
final driver = XDriver.static(
layoutJson,
);
import 'dart:convert';
import 'dart:typed_data';
class CustomDecoder extends Converter<Uint8List, Map<String, dynamic>> {
@override
Map<String, dynamic> convert(Uint8List input) {
// 自定义解码逻辑
return jsonDecode(utf8.decode(input));
}
}
final driver = XDriver(
transportManager: HttpTransportManager(
options: HttpTransportOptions(
baseUrl: 'https://api.example.com',
decoder: CustomDecoder(),
),
),
);
如果需要,创建你自己的传输实现:
class MyCustomTransportManager with TransportCapabilityDelegate {
@override
void linkDriver(UIDriver driver) {
// 实现 linkDriver 方法
}
@override
Stream<Map<String, dynamic>> connect({
Map<String, dynamic>? initialRequestData,
Map<String, dynamic>? staticContent,
}) async* {
// 实现 connect 方法
}
@override
Future<Map<String, dynamic>?> executeRemoteAction(
ServerAction action,
Map<String, dynamic> payload,
) async {
//实现 executeRemoteAction 方法
}
@override
Future<Map<String, dynamic>?> request(
String url,
Map<String, dynamic> meta,
Map<String, dynamic> body,
) async {
//实现 request 方法
}
@override
void releaseResources() {
// 实现 linkDriver 方法
}
}
import 'package:flutter_duit/flutter_duit.dart';
// 1. 定义自定义组件
class MyCustomWidget extends StatelessWidget {
final ViewAttribute attributes;
const MyCustomWidget({
required this.attributes,
super.key,
});
@override
Widget build(BuildContext context) {
final attrs = attributes.payload;
return Container(
child: Text(attrs.getString(key: "message")),
);
}
}
// 2. 为组件创建构建工厂函数
Widget myCustomBuildFactory(ElementPropertyView model) {
if (model.isControlled) {
return MyCustomWidget(
attributes: model.attributes,
);
} else {
return const SizedBox.shrink();
}
}
// 3. 注册构建函数
void main() async {
WidgetsFlutterBinding.ensureInitialized();
DuitRegistry.register(
"MyCustomWidget",
buildFactory: myCustomBuildFactory,
);
runApp(const MyApp());
}
组件允许你创建可重用的 UI 模板,这些模板可以通过标签引用并使用动态数据填充。
import 'package:flutter_duit/flutter_duit.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 定义组件模板
final cardComponent = {
"tag": "CardComponent",
"layoutRoot": {
"type": "Container",
"id": "cardContainer",
"controlled": false,
"attributes": {
"padding": {"all": 16},
"margin": {"all": 8},
"decoration": {
"borderRadius": 12,
"color": "#FFFFFF",
"boxShadow": [
{
"color": "#00000033",
"blurRadius": 6,
"offset": {"dx": 0, "dy": 2},
},
],
},
},
"children": [
{
"type": "Text",
"id": "cardTitle",
"controlled": false,
"attributes": {
"data": {
"style": {
"fontSize": 18,
"fontWeight": "w600",
"color": "#333333",
},
},
"refs": [
{
"objectKey": "title",
"attributeKey": "data",
},
],
},
},
{
"type": "Text",
"id": "cardDescription",
"controlled": false,
"attributes": {
"data": {
"style": {
"fontSize": 14,
"color": "#666666",
},
},
"refs": [
{
"objectKey": "description",
"attributeKey": "data",
},
],
},
},
],
},
};
// 注册组件
await DuitRegistry.registerComponents([cardComponent]);
runApp(const MyApp());
}
// 在服务器 JSON 布局中的用法:
// {
// "type": "Component",
// "id": "card1",
// "tag": "CardComponent",
// "data": {
// "title": "Hello World",
// "description": "This is a card component"
// }
// }
关键概念:
data 字段传递的动态数据的引用data 对象中的键你可以一次注册多个组件:
await DuitRegistry.registerComponents([
cardComponent,
buttonComponent,
listItemComponent,
]);
在以下情况下使用此技能:
每周安装量
145
仓库
GitHub Stars
87
首次出现
2026年1月29日
安全审计
安装于
opencode111
codex106
gemini-cli102
github-copilot94
kimi-cli93
amp92
Duit enables backend-driven UI in Flutter applications. The server controls both data and layout via JSON, allowing UI updates without app releases.
- Dart SDK: >=3.4.4 <4.0.0
- Flutter: >=3.24.0
flutter pub add flutter_duit
Install:
flutter pub get
import 'package:flutter/material.dart';
import 'package:flutter_duit/flutter_duit.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: DuitViewHost.withDriver(
driver: XDriver.static({
"type": "Text",
"id": "1",
"attributes": {"data": "Hello, World!"},
}),
),
),
);
}
}
Always dispose drivers to prevent memory leaks:
class MyWidgetState extends State<MyWidget> {
late final XDriver driver;
@override
void initState() {
super.initState();
driver = XDriver.static(/* ... */);
}
@override
void dispose() {
driver.dispose();
super.dispose();
}
}
Fetch layouts from REST API endpoints:
final driver = XDriver(
transportManager: HttpTransportManager(
options: HttpTransportOptions(
baseUrl: 'https://api.example.com/view',
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
),
),
);
Real-time bidirectional communication:
final driver = XDriver(
transportManager: WSTransportManager(
options: WSTransportOptions(
url: 'wss://api.example.com/ws',
headers: {
'Authorization': 'Bearer $token',
},
reconnectInterval: Duration(seconds: 5),
heartbeatInterval: Duration(seconds: 30),
),
),
);
For testing or local layouts:
final driver = XDriver.static(
layoutJson,
);
import 'dart:convert';
import 'dart:typed_data';
class CustomDecoder extends Converter<Uint8List, Map<String, dynamic>> {
@override
Map<String, dynamic> convert(Uint8List input) {
// Custom decode logic
return jsonDecode(utf8.decode(input));
}
}
final driver = XDriver(
transportManager: HttpTransportManager(
options: HttpTransportOptions(
baseUrl: 'https://api.example.com',
decoder: CustomDecoder(),
),
),
);
Create your own transport implementation if needed:
class MyCustomTransportManager with TransportCapabilityDelegate {
@override
void linkDriver(UIDriver driver) {
// Implement linkDriver method
}
@override
Stream<Map<String, dynamic>> connect({
Map<String, dynamic>? initialRequestData,
Map<String, dynamic>? staticContent,
}) async* {
// Implement connect method
}
@override
Future<Map<String, dynamic>?> executeRemoteAction(
ServerAction action,
Map<String, dynamic> payload,
) async {
//Implement executeRemoteAction method
}
@override
Future<Map<String, dynamic>?> request(
String url,
Map<String, dynamic> meta,
Map<String, dynamic> body,
) async {
//Implement request method
}
@override
void releaseResources() {
// Implement linkDriver method
}
}
import 'package:flutter_duit/flutter_duit.dart';
// 1. Define custom widget
class MyCustomWidget extends StatelessWidget {
final ViewAttribute attributes;
const MyCustomWidget({
required this.attributes,
super.key,
});
@override
Widget build(BuildContext context) {
final attrs = attributes.payload;
return Container(
child: Text(attrs.getString(key: "message")),
);
}
}
// 2. Create build factory fn for widget
Widget myCustomBuildFactory(ElementPropertyView model) {
if (model.isControlled) {
return MyCustomWidget(
attributes: model.attributes,
);
} else {
return const SizedBox.shrink();
}
}
// 3. Register build-fn
void main() async {
WidgetsFlutterBinding.ensureInitialized();
DuitRegistry.register(
"MyCustomWidget",
buildFactory: myCustomBuildFactory,
);
runApp(const MyApp());
}
Components allow you to create reusable UI templates that can be referenced by a tag and populated with dynamic data.
import 'package:flutter_duit/flutter_duit.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Define component template
final cardComponent = {
"tag": "CardComponent",
"layoutRoot": {
"type": "Container",
"id": "cardContainer",
"controlled": false,
"attributes": {
"padding": {"all": 16},
"margin": {"all": 8},
"decoration": {
"borderRadius": 12,
"color": "#FFFFFF",
"boxShadow": [
{
"color": "#00000033",
"blurRadius": 6,
"offset": {"dx": 0, "dy": 2},
},
],
},
},
"children": [
{
"type": "Text",
"id": "cardTitle",
"controlled": false,
"attributes": {
"data": {
"style": {
"fontSize": 18,
"fontWeight": "w600",
"color": "#333333",
},
},
"refs": [
{
"objectKey": "title",
"attributeKey": "data",
},
],
},
},
{
"type": "Text",
"id": "cardDescription",
"controlled": false,
"attributes": {
"data": {
"style": {
"fontSize": 14,
"color": "#666666",
},
},
"refs": [
{
"objectKey": "description",
"attributeKey": "data",
},
],
},
},
],
},
};
// Register the component
await DuitRegistry.registerComponents([cardComponent]);
runApp(const MyApp());
}
// Usage in JSON layout from server:
// {
// "type": "Component",
// "id": "card1",
// "tag": "CardComponent",
// "data": {
// "title": "Hello World",
// "description": "This is a card component"
// }
// }
Key concepts:
data fielddata objectYou can register multiple components at once:
await DuitRegistry.registerComponents([
cardComponent,
buttonComponent,
listItemComponent,
]);
Use this skill when:
Weekly Installs
145
Repository
GitHub Stars
87
First Seen
Jan 29, 2026
Security Audits
Gen Agent Trust HubWarnSocketPassSnykWarn
Installed on
opencode111
codex106
gemini-cli102
github-copilot94
kimi-cli93
amp92
Flutter 主屏幕小组件开发指南:iOS/Android 原生小组件集成与数据通信
3,800 周安装
中国A股实时股票价格查询工具 - Python脚本,支持多股查询与默认指数
208 周安装
Kernel TypeScript SDK:浏览器自动化与Playwright远程执行开发工具
207 周安装
SwiftUI自适应布局指南:ViewThatFits、AnyLayout、Layout协议响应式设计
203 周安装
Excel财务模型自动化处理工具:零错误公式、标准格式与智能分析
205 周安装
Python日志记录最佳实践:Loguru配置、JSONL结构化日志与跨平台日志轮转指南
207 周安装
Vue 2 开发指南 - Options API、组件、Vuex、Vue Router 完整教程
207 周安装