Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问许可证需确认审计通过

flutterFlutter 开发

Agent Skill

flutter 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

196

周安装

8

GitHub Stars

8

下载量

63
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:flutter(Flutter 开发)
来源仓库:https://github.com/ar4mirez/samuel
仓库路径:skills/flutter
安装命令:
npx skills add https://github.com/ar4mirez/samuel --skill flutter
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/ar4mirez/samuel --skill flutter

简介

Flutter 3.x Dart 3.x 跨平台移动/Web 开发规范。

  • 单一代码库覆盖 iOS/Android/Web/桌面全平台。
  • 采用 Widget 组合与声明式 UI 描述界面状态。
  • Riverpod 为首选状态管理解决方案。flutter 属于研究检索类 Skill,可作为该场景下的辅助能力补充。
  • 默认启用 Material 3 设计语言统一视觉体验。

SKILL.md

Flutter Guide

Applies to: Flutter 3.x, Dart 3.x, Mobile (iOS/Android), Web, Desktop

Core Principles

  1. Widget Composition: Build complex UIs by composing small, focused widgets
  2. Declarative UI: Describe what the UI should look like; Flutter handles rendering
  3. Immutable Widgets: Widgets are configuration objects; state lives in State classes or providers
  4. Single Codebase: One Dart codebase targets iOS, Android, Web, macOS, Windows, Linux
  5. Riverpod for State: Use Riverpod as the primary state management solution
  6. Material 3 First: Default to Material 3 design system with useMaterial3: true

Guardrails

Widget Rules

  • Keep widget build methods under 50 lines (extract sub-widgets)
  • Prefer const constructors for all stateless widgets
  • Always use super.key in widget constructors
  • Use ConsumerWidget / ConsumerStatefulWidget when accessing providers
  • Dispose controllers, subscriptions, and animation controllers in dispose()
  • Never perform async work directly in build() -- use providers or FutureBuilder
  • Prefer composition over deep widget nesting (max 5-6 levels in one build method)

State Management (Riverpod)

  • Wrap app root in ProviderScope
  • Use Provider for synchronous values and dependency injection
  • Use StateProvider for simple mutable state (toggles, filters, counters)
  • Use AsyncNotifierProvider for async business logic with CRUD operations
  • Use StreamProvider for real-time data (auth state, WebSocket, Firestore)
  • Use ref.watch() in build methods; use ref.read() in callbacks and event handlers
  • Use ref.listen() for side effects (showing snackbars, navigation)
  • Never call ref.watch() outside of build methods or provider bodies

Navigation (go_router)

  • Define all routes in a single GoRouter configuration
  • Use named routes with context.goNamed() / context.pushNamed()
  • Implement redirect guards for authentication
  • Use ShellRoute for persistent navigation scaffolds (bottom nav, drawer)
  • Use pathParameters for required values, queryParameters for optional filters
  • Define an errorBuilder for unknown routes

File Naming

  • Widgets/screens: snake_case.dart (e.g., user_profile_screen.dart)
  • Providers: snake_case_provider.dart (e.g., auth_provider.dart)
  • Models: snake_case_model.dart (e.g., user_model.dart)
  • Repositories: snake_case_repository.dart
  • Tests: *_test.dart (co-located or in test/ mirroring lib/)

Project Structure

myapp/
├── lib/
│   ├── main.dart                 # Entry point, ProviderScope
│   ├── app.dart                  # MaterialApp.router configuration
│   ├── features/                 # Feature-first organization
│   │   └── auth/
│   │       ├── data/             # Models, repos impl, datasources
│   │       ├── domain/           # Entities, abstract repos, use cases
│   │       └── presentation/     # Screens, widgets, providers
│   ├── core/
│   │   ├── constants/            # App-wide constants
│   │   ├── errors/               # Failure/exception classes
│   │   ├── network/              # API client, interceptors
│   │   ├── router/               # GoRouter configuration
│   │   ├── theme/                # Material 3 theme
│   │   ├── utils/                # Validators, formatters
│   │   └── widgets/              # Shared reusable widgets
│   └── l10n/                     # Localization ARB files
├── test/
│   ├── unit/                     # Provider and logic tests
│   ├── widget/                   # Widget tests
│   └── integration/              # End-to-end tests
├── integration_test/             # Integration test driver
├── pubspec.yaml
└── analysis_options.yaml
  • features/ follows clean architecture: data, domain, presentation layers
  • core/ for cross-cutting concerns shared across features
  • domain/ contains pure Dart (no Flutter imports)
  • data/ handles serialization, networking, and storage

Application Setup

Entry Point

// lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'app.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // Initialize services (Firebase, Hive, etc.) here
  runApp(const ProviderScope(child: MyApp()));
}

App Widget

// lib/app.dart
class MyApp extends ConsumerWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final router = ref.watch(routerProvider);
    return MaterialApp.router(
      title: 'My App',
      theme: AppTheme.light,
      darkTheme: AppTheme.dark,
      themeMode: ThemeMode.system,
      routerConfig: router,
      debugShowCheckedModeBanner: false,
    );
  }
}

Widget Composition

Screen Widget (ConsumerWidget)

class HomeScreen extends ConsumerWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final usersAsync = ref.watch(filteredUsersProvider);

    return Scaffold(
      appBar: AppBar(title: const Text('Users')),
      body: usersAsync.when(
        data: (users) => UserListView(users: users),
        loading: () => const Center(child: CircularProgressIndicator()),
        error: (error, _) => ErrorRetryWidget(
          message: error.toString(),
          onRetry: () => ref.invalidate(usersProvider),
        ),
      ),
    );
  }
}

Stateful Widget Pattern

Use ConsumerStatefulWidget when you need TextEditingController, AnimationController, or other objects that require dispose(). Key patterns:

  • Create controllers in the state class, dispose them in dispose()
  • Use ref.watch() in build() for reactive state
  • Use ref.read() in callbacks like _submit()
  • Use ref.listen() for side effects (snackbars, navigation on error/success)

See references/patterns.md for the full LoginForm example.

State Management (Riverpod)

AsyncNotifier for CRUD

final usersProvider = AsyncNotifierProvider<UsersNotifier, List<User>>(
  UsersNotifier.new,
);

class UsersNotifier extends AsyncNotifier<List<User>> {
  @override
  Future<List<User>> build() async {
    final repo = ref.read(userRepositoryProvider);
    return repo.getUsers();
  }

  Future<void> addUser(User user) async {
    final repo = ref.read(userRepositoryProvider);
    await repo.createUser(user);
    state = AsyncData([...state.value ?? [], user]);
  }

  Future<void> deleteUser(String id) async {
    final repo = ref.read(userRepositoryProvider);
    await repo.deleteUser(id);
    state = AsyncData(
      state.value?.where((u) => u.id != id).toList() ?? [],
    );
  }
}

Derived / Filtered Providers

final searchQueryProvider = StateProvider<String>((ref) => '');

final filteredUsersProvider = Provider<AsyncValue<List<User>>>((ref) {
  final users = ref.watch(usersProvider);
  final query = ref.watch(searchQueryProvider).toLowerCase();
  return users.whenData((list) {
    if (query.isEmpty) return list;
    return list.where((u) => u.name.toLowerCase().contains(query)).toList();
  });
});

Stream Provider (Auth State)

final authStateProvider = StreamProvider<User?>((ref) {
  final repo = ref.watch(authRepositoryProvider);
  return repo.authStateChanges;
});

final currentUserProvider = Provider<User?>((ref) {
  return ref.watch(authStateProvider).valueOrNull;
});

Navigation (go_router)

final routerProvider = Provider<GoRouter>((ref) {
  final authState = ref.watch(authStateProvider);

  return GoRouter(
    initialLocation: '/',
    redirect: (context, state) {
      final isLoggedIn = authState.valueOrNull != null;
      final isOnLogin = state.matchedLocation == '/login';
      if (!isLoggedIn && !isOnLogin) return '/login';
      if (isLoggedIn && isOnLogin) return '/';
      return null;
    },
    routes: [
      GoRoute(
        path: '/login', name: 'login',
        builder: (_, __) => const LoginScreen(),
      ),
      ShellRoute(
        builder: (_, __, child) => ScaffoldWithNavBar(child: child),
        routes: [
          GoRoute(path: '/', name: 'home', builder: (_, __) => const HomeScreen()),
          GoRoute(path: '/profile', name: 'profile', builder: (_, __) => const ProfileScreen()),
          GoRoute(
            path: '/users/:id', name: 'user-detail',
            builder: (_, state) => UserDetailScreen(userId: state.pathParameters['id']!),
          ),
        ],
      ),
    ],
    errorBuilder: (_, state) => ErrorScreen(error: state.error),
  );
});

Theming (Material 3)

class AppTheme {
  AppTheme._();

  static ThemeData get light => ThemeData(
    useMaterial3: true,
    colorScheme: ColorScheme.fromSeed(
      seedColor: const Color(0xFF6750A4),
      brightness: Brightness.light,
    ),
    appBarTheme: const AppBarTheme(centerTitle: true, elevation: 0),
    inputDecorationTheme: InputDecorationTheme(
      border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
      filled: true,
    ),
  );

  static ThemeData get dark => ThemeData(
    useMaterial3: true,
    colorScheme: ColorScheme.fromSeed(
      seedColor: const Color(0xFF6750A4),
      brightness: Brightness.dark,
    ),
  );
}

Data Layer

Freezed Models

@freezed
class UserModel with _$UserModel {
  const UserModel._();
  const factory UserModel({
    required String id,
    required String email,
    required String name,
    @JsonKey(name: 'avatar_url') String? avatarUrl,
    @JsonKey(name: 'created_at') required DateTime createdAt,
  }) = _UserModel;

  factory UserModel.fromJson(Map<String, dynamic> json) =>
      _$UserModelFromJson(json);

  User toEntity() => User(
    id: id, email: email, name: name,
    avatarUrl: avatarUrl, createdAt: createdAt,
  );
}

Repository Pattern

Use abstract interfaces in domain/ and implementations in data/. Repositories return Either<Failure, T> for error handling. Inject via Riverpod Provider:

// domain layer: abstract contract
abstract class AuthRepository {
  Stream<User?> get authStateChanges;
  Future<Either<Failure, User>> signInWithEmailAndPassword(String email, String password);
  Future<Either<Failure, void>> signOut();
}

// provider: inject implementation
final authRepositoryProvider = Provider<AuthRepository>((ref) {
  return AuthRepositoryImpl(
    remoteDataSource: ref.watch(authRemoteDataSourceProvider),
    localDataSource: ref.watch(authLocalDataSourceProvider),
  );
});

See references/patterns.md for full repository implementation and API client patterns.

API Client (Dio)

final dioProvider = Provider<Dio>((ref) {
  return Dio(BaseOptions(
    baseUrl: AppConstants.apiBaseUrl,
    connectTimeout: const Duration(seconds: 30),
    receiveTimeout: const Duration(seconds: 30),
    headers: {'Content-Type': 'application/json'},
  ))..interceptors.addAll([AuthInterceptor(ref), LogInterceptor()]);
});

Platform Channels

When native platform functionality is needed beyond existing packages:

// MethodChannel for one-off calls
static const _channel = MethodChannel('com.example.app/battery');
Future<int> getBatteryLevel() async {
  final level = await _channel.invokeMethod<int>('getBatteryLevel');
  return level ?? -1;
}

// EventChannel for continuous streams
static const _eventChannel = EventChannel('com.example.app/sensors');
Stream<SensorData> get sensorStream =>
    _eventChannel.receiveBroadcastStream().map((e) => SensorData.fromMap(e));

Testing Overview

Widget Test

Widget createWidget() {
  return ProviderScope(
    overrides: [authRepositoryProvider.overrideWithValue(mockRepo)],
    child: const MaterialApp(home: Scaffold(body: LoginForm())),
  );
}

testWidgets('shows validation errors for empty fields', (tester) async {
  await tester.pumpWidget(createWidget());
  await tester.tap(find.text('Sign In'));
  await tester.pump();
  expect(find.text('Email is required'), findsOneWidget);
});

Provider Test

final container = ProviderContainer(
  overrides: [authRepositoryProvider.overrideWithValue(mockRepo)],
);
addTearDown(container.dispose);

test('login success clears error state', () async {
  when(() => mockRepo.signInWithEmailAndPassword(any(), any()))
      .thenAnswer((_) async => Right(testUser));
  await container.read(loginProvider.notifier).login('a@b.com', 'pass');
  expect(container.read(loginProvider).hasError, false);
});

Commands

# Create project
flutter create myapp

# Run
flutter run                           # Default device
flutter run -d chrome                 # Web
flutter run -d macos                  # macOS desktop

# Build
flutter build apk                    # Android APK
flutter build ios                    # iOS archive
flutter build web                    # Web build

# Code generation (Freezed, json_serializable, Riverpod codegen)
dart run build_runner build --delete-conflicting-outputs
dart run build_runner watch           # Continuous generation

# Testing
flutter test                          # All unit + widget tests
flutter test --coverage               # With coverage report
flutter test integration_test/        # Integration tests

# Quality
flutter analyze                       # Static analysis
dart format .                         # Format all files
dart fix --apply                      # Auto-apply lint fixes

Recommended Dependencies

PackagePurpose
flutter_riverpodState management
go_routerDeclarative routing
dioHTTP client with interceptors
freezed_annotation + freezedImmutable data classes (codegen)
json_annotation + json_serializableJSON serialization (codegen)
dartzEither type for error handling
shared_preferencesKey-value local storage
flutter_secure_storageEncrypted credential storage
mocktailMocking for tests (no codegen)
flutter_lintsRecommended lint rules

References

For detailed patterns and examples, see:

  • references/patterns.md -- Widget patterns, animations, networking, local storage, testing, platform-specific code, performance

External References

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

34.99%
按下载量换算22

Claude

27.99%
按下载量换算18

Cursor

19.5%
按下载量换算12

Gemini CLI

9.84%
按下载量换算6

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills