基于 SOC 职业分类
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/JohnNuwan/EVA_CORE --skill flutter命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
Concevoir et maintenir un watchdog auto-correcteur pour services HTTP — checks de santé, auto-restart, état persistant, rapports et pièges bash.
Serveur de messagerie sécurisé auto-hébergé (Signal-like) avec Flask + WebSocket + AES-256-GCM + pont EVA
ADAM-SENTINEL — Veilleur technologique 24h/24h. Scanne 10 domaines, cree des rapports, met a jour les skills, alerte sur les CVE et breaking changes.
| name | flutter |
| description | Développement cross-platform Flutter/Dart — Widget, état, navigation, platform channels, animations, CI/CD, Web |
Développement cross-platform avec Flutter et Dart, couvrant le widget tree, la gestion d'état, la navigation, les animations, les platform channels, et le déploiement iOS/Android/Web/Desktop.
// Null safety
class User {
final String name;
final String? email;
final DateTime createdAt = DateTime.now();
const User({required this.name, this.email});
// Named constructor
User.fromJson(Map<String, dynamic> json)
: name = json['name'] as String,
email = json['email'] as String?;
Map<String, dynamic> toJson() => {
'name': name,
'email': email,
};
}
// Pattern matching (Dart 3)
switch (state) {
case Loading(:final message) => showSpinner(message);
case Success(:final users) => UserList(users);
case Error(:final error) => ErrorWidget(error);
}
// Sealed class
sealed class ApiResult<T> {
const ApiResult();
}
class Success<T> extends ApiResult<T> { final T data; ... }
class Failure<T> extends ApiResult<T> { final String message; ... }
async, await, Future.wait()Stream<T>, StreamSubscription, async*Isolate.spawn, compute() pour CPU-boundStreamController<T>, broadcast streamsrunZonedGuarded pour catch global(String name, int age) record = ('Alice', 30);if-case, switch expression, for-in patternsaugment class, augment methodextension StringParsing on String { int? parseInt() => int.tryParse(this); }<T>, Covariant, Contravariant, T Function()class UserCard extends StatelessWidget {
final User user;
final VoidCallback onTap;
const UserCard({super.key, required this.user, required this.onTap});
@override
Widget build(BuildContext context) {
return Card(
child: InkWell(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
CircleAvatar(backgroundImage: NetworkImage(user.avatarUrl)),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(user.name, style: Theme.of(context).textTheme.titleMedium),
Text(user.email ?? '', style: Theme.of(context).textTheme.bodySmall),
],
),
),
],
),
),
),
);
}
}
MediaQuery.sizeOf(context), orientationMaterialApp(
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF6750A4),
brightness: Brightness.light,
),
typography: Typography.material2021(),
),
darkTheme: ThemeData.dark(),
themeMode: ThemeMode.system,
);
| Approche | Usage | Idéal pour |
|---|---|---|
| StatefulWidget | État local simple | Formulaires, UI state |
| Provider | DI + ChangeNotifier | Petite app |
| Riverpod | Compile-safe Provider | Nouveaux projets |
| Bloc/Cubit | Event-driven | Apps complexes |
| GetX | Tout-en-un | Rapidité (mais controversé) |
// Providers
final userRepositoryProvider = Provider<UserRepository>((ref) => UserRepository());
final fetchUsersProvider = FutureProvider.family<List<User>, String>(
(ref, query) => ref.read(userRepositoryProvider).fetchUsers(query),
);
// StateNotifierProvider
final userListProvider = StateNotifierProvider<UserListNotifier, AsyncValue<List<User>>>((ref) {
return UserListNotifier(ref.read(userRepositoryProvider));
});
class UserListNotifier extends StateNotifier<AsyncValue<List<User>>> {
final UserRepository _repo;
UserListNotifier(this._repo) : super(const AsyncValue.loading());
Future<void> load() async {
state = const AsyncValue.loading();
state = await AsyncValue.guard(() => _repo.fetchUsers());
}
}
// Usage dans le widget
final users = ref.watch(userListProvider);
users.when(
data: (users) => UserList(users),
loading: () => const CircularProgressIndicator(),
error: (err, stack) => ErrorWidget(err.toString()),
);
final router = GoRouter(
initialLocation: '/',
routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomeScreen(),
routes: [
GoRoute(
path: 'user/:id',
builder: (context, state) => UserDetailScreen(
userId: state.pathParameters['id']!,
),
),
],
),
],
);
// Dans MaterialApp.router
MaterialApp.router(routerConfig: router);
GoRouter(
routes: [...],
initialLocation: '/',
debugLogDiagnostics: true,
);
// AndroidManifest.xml intent filter
// Info.plist CFBundleURLTypes
AnimatedContainer(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
width: isExpanded ? 200 : 100,
height: isExpanded ? 200 : 100,
color: isExpanded ? Colors.blue : Colors.red,
)
AnimatedOpacity(
opacity: isVisible ? 1.0 : 0.0,
duration: const Duration(milliseconds: 200),
child: content,
)
class _MyWidgetState extends State<MyWidget> with SingleTickerProviderStateMixin {
late final AnimationController _controller = AnimationController(
duration: const Duration(milliseconds: 500),
vsync: this,
);
late final Animation<double> _animation = CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut,
);
@override
Widget build(BuildContext context) {
return FadeTransition(
opacity: _animation,
child: ScaleTransition(
scale: Tween<double>(begin: 0, end: 1).animate(_animation),
child: content,
),
);
}
}
RiveAnimation.assetLottie.asset, Lottie.repeatHero (shared element), TweenAnimationBuilder// Dart
const platform = MethodChannel('com.example.app/battery');
final batteryLevel = await platform.invokeMethod<int>('getBatteryLevel');
// iOS (Swift)
FlutterMethodChannel(name: "com.example.app/battery", binaryMessenger: controller.binaryMessenger)
.setMethodCallHandler { call, result in
if call.method == "getBatteryLevel" {
result(UIDevice.current.batteryLevel)
}
}
// Android (Kotlin)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "com.example.app/battery")
.setMethodCallHandler { call, result ->
if (call.method == "getBatteryLevel") {
result.success(batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY))
}
}
// Fichier .dart pigeon, génère code natif typé
@HostApi()
abstract class BatteryApi {
int getBatteryLevel();
}
PaintingBinding.instance.imageCache.maximumSize = 500compute() pour traitement lourd (JSON parsing, crypto)--obfuscate --split-debug-infofontVariations vs plusieurs fichiers .ttf.so size pour Flutter engine (ARM64 ≈ 6MB)void main() {
group('UserRepository', () {
late MockApiClient mockApi;
late UserRepository repository;
setUp(() {
mockApi = MockApiClient();
repository = UserRepository(api: mockApi);
});
test('fetchUsers returns list', () async {
when(() => mockApi.getUsers()).thenAnswer((_) async => [testUser]);
final users = await repository.fetchUsers();
expect(users, hasLength(1));
});
});
}
testWidgets('UserCard displays correctly', (tester) async {
await tester.pumpWidget(MaterialApp(
home: UserCard(user: testUser, onTap: () {}),
));
expect(find.text('John Doe'), findsOneWidget);
await tester.tap(find.byType(InkWell));
});
test('login flow', () async {
await app.tap(find.text('Connexion'));
await app.enterText(find.byType(TextField).first, 'user@example.com');
await app.tap(find.text('Valider'));
await app.pumpAndSettle();
expect(find.text('Dashboard'), findsOneWidget);
});
flutter build ios --release # iOS IPA
flutter build apk --release # Android APK
flutter build appbundle --release # Android AAB
flutter build web --release # PWA/Web
flutter build macos --release # macOS DMG
flutter build linux --release # Linux AppImage
flutter build windows --release # Windows MSI
dart:io PlatformkIsWebwindow_manager, menu bar, tray, keyboard shortcutsjobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with:
flutter-version: '3.24'
- run: flutter pub get
- run: flutter build appbundle --release
fastlane match, fastlane deliver, fastlane supplylate final fields, faire hot restartconst manquant = rebuild constants inutilesBouncingScrollPhysics vs ClampingScrollPhysics iOS/AndroidhybridComposition sur Androidflutter pub outdated, dart fix --applySystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky)PHPhotoLibrary, CLLocationManager permission changes