dart-flutter-patterns
Official生产就绪的 Dart 和 Flutter 模式,涵盖空安全、不可变状态、异步组合、Widget 架构、流行的状态管理框架(BLoC、Riverpod、Provider)、GoRouter 导航、Dio 网络请求、Freezed 代码生成和整洁架构。
What this skill does
When applied, it prepends a system prompt before your request is sent — no extra calls and no change to how you are billed beyond the added tokens.
---
name: dart-flutter-patterns
description: 生产就绪的 Dart 和 Flutter 模式,涵盖空安全、不可变状态、异步组合、Widget 架构、流行的状态管理框架(BLoC、Riverpod、Provider)、GoRouter 导航、Dio 网络请求、Freezed 代码生成和整洁架构。
origin: ECC
---
# Dart/Flutter 模式
## 使用场景
在以下情况使用此技能:
* 开始新的 Flutter 功能,需要状态管理、导航或数据访问的惯用模式
* 审查或编写 Dart 代码,需要空安全、密封类型或异步组合的指导
* 搭建新的 Flutter 项目,在 BLoC、Riverpod 或 Provider 之间做选择
* 实现安全的 HTTP 客户端、WebView 集成或本地存储
* 为 Flutter 组件、Cubit 或 Riverpod 提供者编写测试
* 使用认证守卫配置 GoRouter
## 工作原理
此技能提供按关注点组织的、可直接复制粘贴的 Dart/Flutter 代码模式:
1. **空安全** — 避免 `!`,优先使用 `?.`/`??`/模式匹配
2. **不可变状态** — 密封类、`freezed`、`copyWith`
3. **异步组合** — 并发 `Future.wait`、`BuildContext` 后安全使用 `await`
4. **组件架构** — 提取为类(而非方法)、`const` 传播、作用域重建
5. **状态管理** — BLoC/Cubit 事件、Riverpod 通知器和派生提供者
6. **导航** — 通过 `refreshListenable` 实现带响应式认证守卫的 GoRouter
7. **网络请求** — 带拦截器的 Dio、带一次性重试守卫的令牌刷新
8. **错误处理** — 全局捕获、`ErrorWidget.builder`、Crashlytics 集成
9. **测试** — 单元测试(BLoC 测试)、组件测试(ProviderScope 覆盖)、使用假对象而非模拟对象
## 示例
```dart
// Sealed state — prevents impossible states
sealed class AsyncState<T> {}
final class Loading<T> extends AsyncState<T> {}
final class Success<T> extends AsyncState<T> { final T data; const Success(this.data); }
final class Failure<T> extends AsyncState<T> { final Object error; const Failure(this.error); }
// GoRouter with reactive auth redirect
final router = GoRouter(
refreshListenable: GoRouterRefreshStream(authCubit.stream),
redirect: (context, state) {
final authed = context.read<AuthCubit>().state is AuthAuthenticated;
if (!authed && !state.matchedLocation.startsWith('/login')) return '/login';
return null;
},
routes: [...],
);
// Riverpod derived provider with safe firstWhereOrNull
@riverpod
double cartTotal(Ref ref) {
final cart = ref.watch(cartNotifierProvider);
final products = ref.watch(productsProvider).valueOrNull ?? [];
return cart.fold(0.0, (total, item) {
final product = products.firstWhereOrNull((p) => p.id == item.productId);
return total + (product?.price ?? 0) * item.quantity;Use this skill
Add a "skill" field with the skill’s ID to your chat completion request. It is applied server-side before your prompt is sent — no extra calls.
{
"model": "gpt-4o-mini",
"skill": "imp-1f5a3d38-cde3-48f7-9484-d5a1c53d9a5e",
"messages": [{ "role": "user", "content": "…" }]
}Install the skill, enable it in your dashboard and (optionally) limit it to specific models. It then applies automatically to every matching request — with no "skill" field to send each time.
Set it up in your dashboardMore skills
Set up and use 1Password CLI for sign-in, desktop integration, and reading or injecting secrets.
Create, view, edit, delete, search, move, or export Apple Notes via the memo CLI on macOS.
List, add, edit, complete, or delete Apple Reminders and reminder lists via remindctl.
Create, search, and manage Bear notes via grizzly CLI.
Monitor blogs and RSS/Atom feeds for updates using the blogwatcher CLI.
BluOS CLI (blu) for discovery, playback, grouping, and volume.
Capture frames or clips from RTSP/ONVIF cameras.
Search, install, update, sync, or publish agent skills with the ClawHub CLI and registry.