code-abyss 1.6.16 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/package.json +2 -2
  2. package/skills/SKILL.md +24 -16
  3. package/skills/domains/ai/SKILL.md +2 -2
  4. package/skills/domains/ai/prompt-and-eval.md +279 -0
  5. package/skills/domains/architecture/SKILL.md +2 -3
  6. package/skills/domains/architecture/security-arch.md +87 -0
  7. package/skills/domains/data-engineering/SKILL.md +188 -26
  8. package/skills/domains/development/SKILL.md +1 -4
  9. package/skills/domains/devops/SKILL.md +3 -5
  10. package/skills/domains/devops/performance.md +63 -0
  11. package/skills/domains/devops/testing.md +97 -0
  12. package/skills/domains/frontend-design/SKILL.md +12 -3
  13. package/skills/domains/frontend-design/claymorphism/SKILL.md +117 -0
  14. package/skills/domains/frontend-design/claymorphism/references/tokens.css +52 -0
  15. package/skills/domains/frontend-design/engineering.md +287 -0
  16. package/skills/domains/frontend-design/glassmorphism/SKILL.md +138 -0
  17. package/skills/domains/frontend-design/glassmorphism/references/tokens.css +32 -0
  18. package/skills/domains/frontend-design/liquid-glass/SKILL.md +135 -0
  19. package/skills/domains/frontend-design/liquid-glass/references/tokens.css +81 -0
  20. package/skills/domains/frontend-design/neubrutalism/SKILL.md +141 -0
  21. package/skills/domains/frontend-design/neubrutalism/references/tokens.css +44 -0
  22. package/skills/domains/infrastructure/SKILL.md +174 -34
  23. package/skills/domains/mobile/SKILL.md +211 -21
  24. package/skills/domains/orchestration/SKILL.md +1 -0
  25. package/skills/domains/security/SKILL.md +4 -6
  26. package/skills/domains/security/blue-team.md +57 -0
  27. package/skills/domains/security/red-team.md +54 -0
  28. package/skills/domains/security/threat-intel.md +50 -0
  29. package/skills/orchestration/multi-agent/SKILL.md +195 -46
  30. package/skills/run_skill.js +134 -0
  31. package/skills/tools/gen-docs/SKILL.md +6 -4
  32. package/skills/tools/gen-docs/scripts/doc_generator.js +349 -0
  33. package/skills/tools/verify-change/SKILL.md +8 -6
  34. package/skills/tools/verify-change/scripts/change_analyzer.js +270 -0
  35. package/skills/tools/verify-module/SKILL.md +6 -4
  36. package/skills/tools/verify-module/scripts/module_scanner.js +145 -0
  37. package/skills/tools/verify-quality/SKILL.md +5 -3
  38. package/skills/tools/verify-quality/scripts/quality_checker.js +276 -0
  39. package/skills/tools/verify-security/SKILL.md +7 -5
  40. package/skills/tools/verify-security/scripts/security_scanner.js +133 -0
  41. package/skills/__pycache__/run_skill.cpython-312.pyc +0 -0
  42. package/skills/domains/COVERAGE_PLAN.md +0 -232
  43. package/skills/domains/ai/model-evaluation.md +0 -790
  44. package/skills/domains/ai/prompt-engineering.md +0 -703
  45. package/skills/domains/architecture/compliance.md +0 -299
  46. package/skills/domains/architecture/data-security.md +0 -184
  47. package/skills/domains/data-engineering/data-pipeline.md +0 -762
  48. package/skills/domains/data-engineering/data-quality.md +0 -894
  49. package/skills/domains/data-engineering/stream-processing.md +0 -791
  50. package/skills/domains/development/dart.md +0 -963
  51. package/skills/domains/development/kotlin.md +0 -834
  52. package/skills/domains/development/php.md +0 -659
  53. package/skills/domains/development/swift.md +0 -755
  54. package/skills/domains/devops/e2e-testing.md +0 -914
  55. package/skills/domains/devops/performance-testing.md +0 -734
  56. package/skills/domains/devops/testing-strategy.md +0 -667
  57. package/skills/domains/frontend-design/build-tools.md +0 -743
  58. package/skills/domains/frontend-design/performance.md +0 -734
  59. package/skills/domains/frontend-design/testing.md +0 -699
  60. package/skills/domains/infrastructure/gitops.md +0 -735
  61. package/skills/domains/infrastructure/iac.md +0 -855
  62. package/skills/domains/infrastructure/kubernetes.md +0 -1018
  63. package/skills/domains/mobile/android-dev.md +0 -979
  64. package/skills/domains/mobile/cross-platform.md +0 -795
  65. package/skills/domains/mobile/ios-dev.md +0 -931
  66. package/skills/domains/security/secrets-management.md +0 -834
  67. package/skills/domains/security/supply-chain.md +0 -931
  68. package/skills/domains/security/threat-modeling.md +0 -828
  69. package/skills/run_skill.py +0 -153
  70. package/skills/tests/README.md +0 -225
  71. package/skills/tests/SUMMARY.md +0 -362
  72. package/skills/tests/__init__.py +0 -3
  73. package/skills/tests/__pycache__/test_change_analyzer.cpython-312.pyc +0 -0
  74. package/skills/tests/__pycache__/test_doc_generator.cpython-312.pyc +0 -0
  75. package/skills/tests/__pycache__/test_module_scanner.cpython-312.pyc +0 -0
  76. package/skills/tests/__pycache__/test_quality_checker.cpython-312.pyc +0 -0
  77. package/skills/tests/__pycache__/test_security_scanner.cpython-312.pyc +0 -0
  78. package/skills/tests/test_change_analyzer.py +0 -558
  79. package/skills/tests/test_doc_generator.py +0 -538
  80. package/skills/tests/test_module_scanner.py +0 -376
  81. package/skills/tests/test_quality_checker.py +0 -516
  82. package/skills/tests/test_security_scanner.py +0 -426
  83. package/skills/tools/gen-docs/scripts/__pycache__/doc_generator.cpython-312.pyc +0 -0
  84. package/skills/tools/gen-docs/scripts/doc_generator.py +0 -520
  85. package/skills/tools/verify-change/scripts/__pycache__/change_analyzer.cpython-312.pyc +0 -0
  86. package/skills/tools/verify-change/scripts/change_analyzer.py +0 -529
  87. package/skills/tools/verify-module/scripts/__pycache__/module_scanner.cpython-312.pyc +0 -0
  88. package/skills/tools/verify-module/scripts/module_scanner.py +0 -321
  89. package/skills/tools/verify-quality/scripts/__pycache__/quality_checker.cpython-312.pyc +0 -0
  90. package/skills/tools/verify-quality/scripts/quality_checker.py +0 -481
  91. package/skills/tools/verify-security/scripts/__pycache__/security_scanner.cpython-312.pyc +0 -0
  92. package/skills/tools/verify-security/scripts/security_scanner.py +0 -374
@@ -1,963 +0,0 @@
1
- ---
2
- name: dart
3
- description: Dart 开发技术。Flutter、Widget 树、异步编程、Future、Stream、跨平台开发。当用户提到 Dart、Flutter、Widget、跨平台、移动开发时使用。
4
- ---
5
-
6
- # 🎯 Dart 开发 · Dart Development
7
-
8
- ## 生态架构
9
-
10
- ```
11
- Flutter Framework
12
-
13
- ┌─────────┼─────────┐
14
- │ │ │
15
- Widgets Material Cupertino
16
- │ │ │
17
- └─────────┼─────────┘
18
-
19
- Dart Runtime
20
-
21
- ┌─────────┼─────────┐
22
- Future Stream Isolate
23
- ```
24
-
25
- ## Dart 语言基础
26
-
27
- ### 变量与类型
28
- ```dart
29
- // 类型推断
30
- var name = 'John';
31
- var age = 30;
32
-
33
- // 显式类型
34
- String email = 'john@example.com';
35
- int count = 0;
36
- double price = 99.99;
37
- bool isActive = true;
38
-
39
- // 可空类型
40
- String? nullableName;
41
- int? nullableAge;
42
-
43
- // late 延迟初始化
44
- late String description;
45
-
46
- // final 与 const
47
- final currentTime = DateTime.now(); // 运行时常量
48
- const pi = 3.14159; // 编译时常量
49
-
50
- // 集合
51
- List<String> names = ['Alice', 'Bob', 'Charlie'];
52
- Set<int> uniqueNumbers = {1, 2, 3};
53
- Map<String, int> scores = {'Alice': 95, 'Bob': 87};
54
- ```
55
-
56
- ### 函数与闭包
57
- ```dart
58
- // 基础函数
59
- int add(int a, int b) {
60
- return a + b;
61
- }
62
-
63
- // 箭头函数
64
- int multiply(int a, int b) => a * b;
65
-
66
- // 可选参数
67
- String greet(String name, [String? title]) {
68
- return title != null ? '$title $name' : name;
69
- }
70
-
71
- // 命名参数
72
- void printUser({required String name, int age = 0}) {
73
- print('$name is $age years old');
74
- }
75
-
76
- // 高阶函数
77
- List<T> transform<T>(List<T> items, T Function(T) transformer) {
78
- return items.map(transformer).toList();
79
- }
80
-
81
- // 闭包
82
- Function makeAdder(int addBy) {
83
- return (int i) => i + addBy;
84
- }
85
-
86
- var add2 = makeAdder(2);
87
- print(add2(3)); // 5
88
- ```
89
-
90
- ### 类与继承
91
- ```dart
92
- // 基础类
93
- class Person {
94
- String name;
95
- int age;
96
-
97
- // 构造函数
98
- Person(this.name, this.age);
99
-
100
- // 命名构造函数
101
- Person.guest() : name = 'Guest', age = 0;
102
-
103
- // 方法
104
- void introduce() {
105
- print('I am $name, $age years old');
106
- }
107
- }
108
-
109
- // 继承
110
- class Student extends Person {
111
- String school;
112
-
113
- Student(String name, int age, this.school) : super(name, age);
114
-
115
- @override
116
- void introduce() {
117
- super.introduce();
118
- print('I study at $school');
119
- }
120
- }
121
-
122
- // 抽象类
123
- abstract class Animal {
124
- String name;
125
- Animal(this.name);
126
-
127
- void makeSound(); // 抽象方法
128
- }
129
-
130
- class Dog extends Animal {
131
- Dog(String name) : super(name);
132
-
133
- @override
134
- void makeSound() {
135
- print('$name says: Woof!');
136
- }
137
- }
138
-
139
- // Mixin
140
- mixin Flyable {
141
- void fly() {
142
- print('Flying...');
143
- }
144
- }
145
-
146
- class Bird extends Animal with Flyable {
147
- Bird(String name) : super(name);
148
-
149
- @override
150
- void makeSound() {
151
- print('$name says: Chirp!');
152
- }
153
- }
154
- ```
155
-
156
- ## Flutter Widget 基础
157
-
158
- ### StatelessWidget
159
- ```dart
160
- import 'package:flutter/material.dart';
161
-
162
- class UserCard extends StatelessWidget {
163
- final String name;
164
- final String email;
165
- final String? avatarUrl;
166
-
167
- const UserCard({
168
- Key? key,
169
- required this.name,
170
- required this.email,
171
- this.avatarUrl,
172
- }) : super(key: key);
173
-
174
- @override
175
- Widget build(BuildContext context) {
176
- return Card(
177
- margin: EdgeInsets.all(16),
178
- child: Padding(
179
- padding: EdgeInsets.all(16),
180
- child: Row(
181
- children: [
182
- CircleAvatar(
183
- radius: 30,
184
- backgroundImage: avatarUrl != null
185
- ? NetworkImage(avatarUrl!)
186
- : null,
187
- child: avatarUrl == null ? Icon(Icons.person) : null,
188
- ),
189
- SizedBox(width: 16),
190
- Expanded(
191
- child: Column(
192
- crossAxisAlignment: CrossAxisAlignment.start,
193
- children: [
194
- Text(
195
- name,
196
- style: Theme.of(context).textTheme.titleLarge,
197
- ),
198
- SizedBox(height: 4),
199
- Text(
200
- email,
201
- style: Theme.of(context).textTheme.bodyMedium,
202
- ),
203
- ],
204
- ),
205
- ),
206
- ],
207
- ),
208
- ),
209
- );
210
- }
211
- }
212
- ```
213
-
214
- ### StatefulWidget
215
- ```dart
216
- class Counter extends StatefulWidget {
217
- const Counter({Key? key}) : super(key: key);
218
-
219
- @override
220
- State<Counter> createState() => _CounterState();
221
- }
222
-
223
- class _CounterState extends State<Counter> {
224
- int _count = 0;
225
-
226
- void _increment() {
227
- setState(() {
228
- _count++;
229
- });
230
- }
231
-
232
- @override
233
- Widget build(BuildContext context) {
234
- return Column(
235
- mainAxisAlignment: MainAxisAlignment.center,
236
- children: [
237
- Text(
238
- 'Count: $_count',
239
- style: Theme.of(context).textTheme.headlineMedium,
240
- ),
241
- SizedBox(height: 16),
242
- ElevatedButton(
243
- onPressed: _increment,
244
- child: Text('Increment'),
245
- ),
246
- ],
247
- );
248
- }
249
- }
250
- ```
251
-
252
- ### 布局 Widget
253
- ```dart
254
- class LayoutExample extends StatelessWidget {
255
- @override
256
- Widget build(BuildContext context) {
257
- return Scaffold(
258
- appBar: AppBar(title: Text('Layout Example')),
259
- body: Column(
260
- children: [
261
- // Row 水平布局
262
- Row(
263
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
264
- children: [
265
- Icon(Icons.star),
266
- Icon(Icons.favorite),
267
- Icon(Icons.thumb_up),
268
- ],
269
- ),
270
-
271
- // Stack 层叠布局
272
- Stack(
273
- children: [
274
- Container(
275
- width: 200,
276
- height: 200,
277
- color: Colors.blue,
278
- ),
279
- Positioned(
280
- top: 20,
281
- left: 20,
282
- child: Text('Overlay Text'),
283
- ),
284
- ],
285
- ),
286
-
287
- // Expanded 填充剩余空间
288
- Expanded(
289
- child: Container(
290
- color: Colors.grey[200],
291
- child: Center(child: Text('Expanded Area')),
292
- ),
293
- ),
294
-
295
- // ListView
296
- Expanded(
297
- child: ListView.builder(
298
- itemCount: 20,
299
- itemBuilder: (context, index) {
300
- return ListTile(
301
- leading: Icon(Icons.person),
302
- title: Text('Item $index'),
303
- subtitle: Text('Description'),
304
- trailing: Icon(Icons.chevron_right),
305
- );
306
- },
307
- ),
308
- ),
309
- ],
310
- ),
311
- );
312
- }
313
- }
314
- ```
315
-
316
- ### 导航与路由
317
- ```dart
318
- // 基础导航
319
- Navigator.push(
320
- context,
321
- MaterialPageRoute(builder: (context) => DetailScreen()),
322
- );
323
-
324
- Navigator.pop(context);
325
-
326
- // 命名路由
327
- MaterialApp(
328
- initialRoute: '/',
329
- routes: {
330
- '/': (context) => HomeScreen(),
331
- '/detail': (context) => DetailScreen(),
332
- '/settings': (context) => SettingsScreen(),
333
- },
334
- );
335
-
336
- Navigator.pushNamed(context, '/detail');
337
-
338
- // 传递参数
339
- Navigator.pushNamed(
340
- context,
341
- '/detail',
342
- arguments: {'id': '123', 'name': 'Item'},
343
- );
344
-
345
- // 接收参数
346
- class DetailScreen extends StatelessWidget {
347
- @override
348
- Widget build(BuildContext context) {
349
- final args = ModalRoute.of(context)!.settings.arguments as Map;
350
- return Scaffold(
351
- appBar: AppBar(title: Text(args['name'])),
352
- body: Center(child: Text('ID: ${args['id']}')),
353
- );
354
- }
355
- }
356
- ```
357
-
358
- ## 状态管理
359
-
360
- ### Provider
361
- ```dart
362
- import 'package:provider/provider.dart';
363
-
364
- // Model
365
- class Counter with ChangeNotifier {
366
- int _count = 0;
367
-
368
- int get count => _count;
369
-
370
- void increment() {
371
- _count++;
372
- notifyListeners();
373
- }
374
-
375
- void reset() {
376
- _count = 0;
377
- notifyListeners();
378
- }
379
- }
380
-
381
- // 提供者
382
- void main() {
383
- runApp(
384
- ChangeNotifierProvider(
385
- create: (context) => Counter(),
386
- child: MyApp(),
387
- ),
388
- );
389
- }
390
-
391
- // 消费者
392
- class CounterScreen extends StatelessWidget {
393
- @override
394
- Widget build(BuildContext context) {
395
- return Scaffold(
396
- appBar: AppBar(title: Text('Counter')),
397
- body: Center(
398
- child: Column(
399
- mainAxisAlignment: MainAxisAlignment.center,
400
- children: [
401
- Consumer<Counter>(
402
- builder: (context, counter, child) {
403
- return Text(
404
- 'Count: ${counter.count}',
405
- style: Theme.of(context).textTheme.headlineMedium,
406
- );
407
- },
408
- ),
409
- SizedBox(height: 16),
410
- ElevatedButton(
411
- onPressed: () {
412
- context.read<Counter>().increment();
413
- },
414
- child: Text('Increment'),
415
- ),
416
- ],
417
- ),
418
- ),
419
- );
420
- }
421
- }
422
- ```
423
-
424
- ### Riverpod
425
- ```dart
426
- import 'package:flutter_riverpod/flutter_riverpod.dart';
427
-
428
- // Provider 定义
429
- final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
430
- return CounterNotifier();
431
- });
432
-
433
- class CounterNotifier extends StateNotifier<int> {
434
- CounterNotifier() : super(0);
435
-
436
- void increment() => state++;
437
- void decrement() => state--;
438
- }
439
-
440
- // 使用
441
- class CounterScreen extends ConsumerWidget {
442
- @override
443
- Widget build(BuildContext context, WidgetRef ref) {
444
- final count = ref.watch(counterProvider);
445
-
446
- return Scaffold(
447
- body: Center(
448
- child: Column(
449
- mainAxisAlignment: MainAxisAlignment.center,
450
- children: [
451
- Text('Count: $count'),
452
- ElevatedButton(
453
- onPressed: () => ref.read(counterProvider.notifier).increment(),
454
- child: Text('Increment'),
455
- ),
456
- ],
457
- ),
458
- ),
459
- );
460
- }
461
- }
462
- ```
463
-
464
- ## 异步编程
465
-
466
- ### Future
467
- ```dart
468
- // 基础 Future
469
- Future<String> fetchUserName() async {
470
- await Future.delayed(Duration(seconds: 2));
471
- return 'John Doe';
472
- }
473
-
474
- // 使用 async/await
475
- void loadUser() async {
476
- try {
477
- final name = await fetchUserName();
478
- print('User: $name');
479
- } catch (e) {
480
- print('Error: $e');
481
- }
482
- }
483
-
484
- // Future.then
485
- fetchUserName().then((name) {
486
- print('User: $name');
487
- }).catchError((error) {
488
- print('Error: $error');
489
- });
490
-
491
- // 并发执行
492
- Future<void> loadMultipleData() async {
493
- final results = await Future.wait([
494
- fetchUserName(),
495
- fetchUserEmail(),
496
- fetchUserAge(),
497
- ]);
498
-
499
- print('Name: ${results[0]}');
500
- print('Email: ${results[1]}');
501
- print('Age: ${results[2]}');
502
- }
503
-
504
- // FutureBuilder Widget
505
- class UserProfile extends StatelessWidget {
506
- @override
507
- Widget build(BuildContext context) {
508
- return FutureBuilder<User>(
509
- future: fetchUser(),
510
- builder: (context, snapshot) {
511
- if (snapshot.connectionState == ConnectionState.waiting) {
512
- return CircularProgressIndicator();
513
- }
514
-
515
- if (snapshot.hasError) {
516
- return Text('Error: ${snapshot.error}');
517
- }
518
-
519
- if (!snapshot.hasData) {
520
- return Text('No data');
521
- }
522
-
523
- final user = snapshot.data!;
524
- return Text('User: ${user.name}');
525
- },
526
- );
527
- }
528
- }
529
- ```
530
-
531
- ### Stream
532
- ```dart
533
- // 创建 Stream
534
- Stream<int> countStream() async* {
535
- for (int i = 1; i <= 5; i++) {
536
- await Future.delayed(Duration(seconds: 1));
537
- yield i;
538
- }
539
- }
540
-
541
- // 监听 Stream
542
- void listenToStream() {
543
- countStream().listen(
544
- (value) {
545
- print('Value: $value');
546
- },
547
- onError: (error) {
548
- print('Error: $error');
549
- },
550
- onDone: () {
551
- print('Stream completed');
552
- },
553
- );
554
- }
555
-
556
- // StreamController
557
- class ChatService {
558
- final _messageController = StreamController<String>.broadcast();
559
-
560
- Stream<String> get messages => _messageController.stream;
561
-
562
- void sendMessage(String message) {
563
- _messageController.add(message);
564
- }
565
-
566
- void dispose() {
567
- _messageController.close();
568
- }
569
- }
570
-
571
- // StreamBuilder Widget
572
- class MessageList extends StatelessWidget {
573
- final ChatService chatService;
574
-
575
- const MessageList({required this.chatService});
576
-
577
- @override
578
- Widget build(BuildContext context) {
579
- return StreamBuilder<String>(
580
- stream: chatService.messages,
581
- builder: (context, snapshot) {
582
- if (snapshot.hasError) {
583
- return Text('Error: ${snapshot.error}');
584
- }
585
-
586
- if (!snapshot.hasData) {
587
- return Text('No messages');
588
- }
589
-
590
- return Text('Latest: ${snapshot.data}');
591
- },
592
- );
593
- }
594
- }
595
-
596
- // Stream 操作符
597
- Stream<int> transformedStream() {
598
- return countStream()
599
- .where((value) => value % 2 == 0)
600
- .map((value) => value * 2)
601
- .take(3);
602
- }
603
- ```
604
-
605
- ## 网络请求
606
-
607
- ### HTTP 包
608
- ```dart
609
- import 'package:http/http.dart' as http;
610
- import 'dart:convert';
611
-
612
- class ApiClient {
613
- static const baseUrl = 'https://api.example.com';
614
-
615
- Future<List<User>> fetchUsers() async {
616
- final response = await http.get(Uri.parse('$baseUrl/users'));
617
-
618
- if (response.statusCode == 200) {
619
- final List<dynamic> data = json.decode(response.body);
620
- return data.map((json) => User.fromJson(json)).toList();
621
- } else {
622
- throw Exception('Failed to load users');
623
- }
624
- }
625
-
626
- Future<User> createUser(User user) async {
627
- final response = await http.post(
628
- Uri.parse('$baseUrl/users'),
629
- headers: {'Content-Type': 'application/json'},
630
- body: json.encode(user.toJson()),
631
- );
632
-
633
- if (response.statusCode == 201) {
634
- return User.fromJson(json.decode(response.body));
635
- } else {
636
- throw Exception('Failed to create user');
637
- }
638
- }
639
-
640
- Future<void> deleteUser(String id) async {
641
- final response = await http.delete(
642
- Uri.parse('$baseUrl/users/$id'),
643
- );
644
-
645
- if (response.statusCode != 204) {
646
- throw Exception('Failed to delete user');
647
- }
648
- }
649
- }
650
-
651
- // 数据模型
652
- class User {
653
- final String id;
654
- final String name;
655
- final String email;
656
-
657
- User({required this.id, required this.name, required this.email});
658
-
659
- factory User.fromJson(Map<String, dynamic> json) {
660
- return User(
661
- id: json['id'],
662
- name: json['name'],
663
- email: json['email'],
664
- );
665
- }
666
-
667
- Map<String, dynamic> toJson() {
668
- return {
669
- 'id': id,
670
- 'name': name,
671
- 'email': email,
672
- };
673
- }
674
- }
675
- ```
676
-
677
- ### Dio 包
678
- ```dart
679
- import 'package:dio/dio.dart';
680
-
681
- class DioClient {
682
- final Dio _dio = Dio(
683
- BaseOptions(
684
- baseUrl: 'https://api.example.com',
685
- connectTimeout: Duration(seconds: 5),
686
- receiveTimeout: Duration(seconds: 3),
687
- ),
688
- );
689
-
690
- DioClient() {
691
- _dio.interceptors.add(
692
- InterceptorsWrapper(
693
- onRequest: (options, handler) {
694
- options.headers['Authorization'] = 'Bearer $token';
695
- return handler.next(options);
696
- },
697
- onError: (error, handler) {
698
- print('Error: ${error.message}');
699
- return handler.next(error);
700
- },
701
- ),
702
- );
703
- }
704
-
705
- Future<List<User>> getUsers() async {
706
- try {
707
- final response = await _dio.get('/users');
708
- return (response.data as List)
709
- .map((json) => User.fromJson(json))
710
- .toList();
711
- } on DioException catch (e) {
712
- throw _handleError(e);
713
- }
714
- }
715
-
716
- Exception _handleError(DioException error) {
717
- switch (error.type) {
718
- case DioExceptionType.connectionTimeout:
719
- return Exception('Connection timeout');
720
- case DioExceptionType.receiveTimeout:
721
- return Exception('Receive timeout');
722
- case DioExceptionType.badResponse:
723
- return Exception('Server error: ${error.response?.statusCode}');
724
- default:
725
- return Exception('Network error');
726
- }
727
- }
728
- }
729
- ```
730
-
731
- ## 本地存储
732
-
733
- ### SharedPreferences
734
- ```dart
735
- import 'package:shared_preferences/shared_preferences.dart';
736
-
737
- class PreferencesService {
738
- Future<void> saveString(String key, String value) async {
739
- final prefs = await SharedPreferences.getInstance();
740
- await prefs.setString(key, value);
741
- }
742
-
743
- Future<String?> getString(String key) async {
744
- final prefs = await SharedPreferences.getInstance();
745
- return prefs.getString(key);
746
- }
747
-
748
- Future<void> saveInt(String key, int value) async {
749
- final prefs = await SharedPreferences.getInstance();
750
- await prefs.setInt(key, value);
751
- }
752
-
753
- Future<void> saveBool(String key, bool value) async {
754
- final prefs = await SharedPreferences.getInstance();
755
- await prefs.setBool(key, value);
756
- }
757
-
758
- Future<void> remove(String key) async {
759
- final prefs = await SharedPreferences.getInstance();
760
- await prefs.remove(key);
761
- }
762
- }
763
- ```
764
-
765
- ### SQLite (sqflite)
766
- ```dart
767
- import 'package:sqflite/sqflite.dart';
768
- import 'package:path/path.dart';
769
-
770
- class DatabaseHelper {
771
- static final DatabaseHelper instance = DatabaseHelper._init();
772
- static Database? _database;
773
-
774
- DatabaseHelper._init();
775
-
776
- Future<Database> get database async {
777
- if (_database != null) return _database!;
778
- _database = await _initDB('app.db');
779
- return _database!;
780
- }
781
-
782
- Future<Database> _initDB(String filePath) async {
783
- final dbPath = await getDatabasesPath();
784
- final path = join(dbPath, filePath);
785
-
786
- return await openDatabase(
787
- path,
788
- version: 1,
789
- onCreate: _createDB,
790
- );
791
- }
792
-
793
- Future _createDB(Database db, int version) async {
794
- await db.execute('''
795
- CREATE TABLE users (
796
- id TEXT PRIMARY KEY,
797
- name TEXT NOT NULL,
798
- email TEXT NOT NULL,
799
- created_at INTEGER NOT NULL
800
- )
801
- ''');
802
- }
803
-
804
- Future<void> insertUser(User user) async {
805
- final db = await database;
806
- await db.insert('users', user.toMap());
807
- }
808
-
809
- Future<List<User>> getUsers() async {
810
- final db = await database;
811
- final result = await db.query('users');
812
- return result.map((json) => User.fromMap(json)).toList();
813
- }
814
-
815
- Future<void> deleteUser(String id) async {
816
- final db = await database;
817
- await db.delete('users', where: 'id = ?', whereArgs: [id]);
818
- }
819
- }
820
- ```
821
-
822
- ## 测试
823
-
824
- ### 单元测试
825
- ```dart
826
- import 'package:test/test.dart';
827
-
828
- void main() {
829
- group('Calculator', () {
830
- late Calculator calculator;
831
-
832
- setUp(() {
833
- calculator = Calculator();
834
- });
835
-
836
- test('addition should return correct result', () {
837
- expect(calculator.add(2, 3), equals(5));
838
- });
839
-
840
- test('division by zero should throw exception', () {
841
- expect(() => calculator.divide(10, 0), throwsException);
842
- });
843
- });
844
-
845
- group('User', () {
846
- test('fromJson should create valid user', () {
847
- final json = {'id': '1', 'name': 'John', 'email': 'john@example.com'};
848
- final user = User.fromJson(json);
849
-
850
- expect(user.id, equals('1'));
851
- expect(user.name, equals('John'));
852
- expect(user.email, equals('john@example.com'));
853
- });
854
- });
855
- }
856
- ```
857
-
858
- ### Widget 测试
859
- ```dart
860
- import 'package:flutter_test/flutter_test.dart';
861
-
862
- void main() {
863
- testWidgets('Counter increments', (WidgetTester tester) async {
864
- await tester.pumpWidget(MaterialApp(home: Counter()));
865
-
866
- expect(find.text('Count: 0'), findsOneWidget);
867
- expect(find.text('Count: 1'), findsNothing);
868
-
869
- await tester.tap(find.byType(ElevatedButton));
870
- await tester.pump();
871
-
872
- expect(find.text('Count: 0'), findsNothing);
873
- expect(find.text('Count: 1'), findsOneWidget);
874
- });
875
-
876
- testWidgets('UserCard displays user info', (WidgetTester tester) async {
877
- await tester.pumpWidget(
878
- MaterialApp(
879
- home: Scaffold(
880
- body: UserCard(
881
- name: 'John Doe',
882
- email: 'john@example.com',
883
- ),
884
- ),
885
- ),
886
- );
887
-
888
- expect(find.text('John Doe'), findsOneWidget);
889
- expect(find.text('john@example.com'), findsOneWidget);
890
- });
891
- }
892
- ```
893
-
894
- ## 性能优化
895
-
896
- ### 列表优化
897
- ```dart
898
- // ✅ 使用 ListView.builder
899
- ListView.builder(
900
- itemCount: items.length,
901
- itemBuilder: (context, index) {
902
- return ItemWidget(items[index]);
903
- },
904
- );
905
-
906
- // ❌ 避免直接使用 ListView
907
- ListView(
908
- children: items.map((item) => ItemWidget(item)).toList(),
909
- );
910
-
911
- // const 构造函数
912
- class MyWidget extends StatelessWidget {
913
- const MyWidget({Key? key}) : super(key: key);
914
-
915
- @override
916
- Widget build(BuildContext context) {
917
- return const Text('Static text');
918
- }
919
- }
920
- ```
921
-
922
- ### 图片优化
923
- ```dart
924
- // 缓存网络图片
925
- CachedNetworkImage(
926
- imageUrl: 'https://example.com/image.jpg',
927
- placeholder: (context, url) => CircularProgressIndicator(),
928
- errorWidget: (context, url, error) => Icon(Icons.error),
929
- );
930
-
931
- // 图片压缩
932
- Image.network(
933
- 'https://example.com/image.jpg',
934
- cacheWidth: 300,
935
- cacheHeight: 300,
936
- );
937
- ```
938
-
939
- ## 平台对比
940
-
941
- | 特性 | Flutter | React Native |
942
- |------|---------|--------------|
943
- | 语言 | Dart | JavaScript |
944
- | 性能 | 接近原生 | 较好 |
945
- | UI 渲染 | Skia 引擎 | 原生组件 |
946
- | 热重载 | ✅ | ✅ |
947
- | 学习曲线 | 中等 | 平缓 |
948
- | 生态 | 快速增长 | 成熟 |
949
-
950
- ## 工具清单
951
-
952
- | 工具 | 用途 |
953
- |------|------|
954
- | Flutter SDK | 开发框架 |
955
- | Dart DevTools | 调试工具 |
956
- | Provider | 状态管理 |
957
- | Riverpod | 状态管理 |
958
- | Dio | 网络请求 |
959
- | sqflite | SQLite 数据库 |
960
- | shared_preferences | 键值存储 |
961
- | flutter_test | 测试框架 |
962
-
963
- ---