dart-expert
Dart・Flutter・モバイル開発・クロスプラットフォームアプリに関するエキスパートレベルの支援を提供します。アーキテクチャ設計からパフォーマンス最適化まで、実践的な実装課題に幅広く対応します。
description の原文を見る
Expert-level Dart, Flutter, mobile development, and cross-platform apps
SKILL.md 本文
Dart & Flutter エキスパート
Dart プログラミング、Flutter フレームワーク、モバイル開発、およびクロスプラットフォーム アプリケーション開発に関するエキスパート レベルのガイダンスを提供します。
コア コンセプト
Dart 言語
- 型推論を備えた強い型付け
- Async/await と Future
- ストリーム
- Mixin と拡張
- Null 安全性
- コレクション
Flutter フレームワーク
- ウィジェット (ステートレス & ステートフル)
- 状態管理 (Provider、Riverpod、Bloc)
- ナビゲーション とルーティング
- Material と Cupertino デザイン
- レスポンシブ レイアウト
- プラットフォーム統合
Dart の基礎
// Variables and types
var name = 'John'; // Type inference
String explicitType = 'Explicit';
final constantValue = 42; // Runtime constant
const compileConstant = 'Compile-time';
// Null safety
String? nullableString;
String nonNullable = 'Never null';
// Late initialization
late String lateInit;
// Collections
List<String> names = ['Alice', 'Bob', 'Charlie'];
Map<String, int> ages = {'Alice': 25, 'Bob': 30};
Set<int> uniqueNumbers = {1, 2, 3, 3}; // {1, 2, 3}
// Functions
int add(int a, int b) => a + b;
// Named parameters
void createUser({
required String name,
int age = 18,
String? email,
}) {
print('Creating user: $name, age: $age');
}
// Classes
class User {
final String id;
final String name;
int age;
User({
required this.id,
required this.name,
this.age = 0,
});
// Named constructor
User.guest() : this(id: 'guest', name: 'Guest');
// Methods
void celebrateBirthday() {
age++;
}
@override
String toString() => 'User($name, $age)';
}
// Mixins
mixin Loggable {
void log(String message) {
print('[${DateTime.now()}] $message');
}
}
class LoggableUser extends User with Loggable {
LoggableUser({required String id, required String name})
: super(id: id, name: name);
}
// Extensions
extension StringExtensions on String {
bool get isValidEmail => contains('@') && contains('.');
String capitalize() => '${this[0].toUpperCase()}${substring(1)}';
}
非同期プログラミング
import 'dart:async';
// Future
Future<String> fetchUser(String id) async {
await Future.delayed(Duration(seconds: 1));
return 'User $id';
}
// Error handling
Future<User?> fetchUserSafely(String id) async {
try {
final user = await fetchUser(id);
return User(id: id, name: user);
} catch (e) {
print('Error: $e');
return null;
}
}
// Multiple futures
Future<void> fetchMultiple() async {
final results = await Future.wait([
fetchUser('1'),
fetchUser('2'),
fetchUser('3'),
]);
print(results);
}
// Streams
Stream<int> countStream() async* {
for (int i = 1; i <= 5; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
// Listen to stream
void listenToStream() {
countStream().listen(
(data) => print('Received: $data'),
onError: (error) => print('Error: $error'),
onDone: () => print('Done'),
);
}
// Stream transformations
Stream<String> transformedStream() {
return countStream()
.where((n) => n % 2 == 0)
.map((n) => 'Number: $n')
.take(3);
}
// StreamController
class Counter {
final _controller = StreamController<int>();
Stream<int> get stream => _controller.stream;
void increment(int value) {
_controller.add(value);
}
void dispose() {
_controller.close();
}
}
Flutter ウィジェット
import 'package:flutter/material.dart';
// Stateless Widget
class UserCard extends StatelessWidget {
final User user;
const UserCard({Key? key, required this.user}) : super(key: key);
@override
Widget build(BuildContext context) {
return Card(
child: ListTile(
title: Text(user.name),
subtitle: Text('Age: ${user.age}'),
trailing: Icon(Icons.arrow_forward),
),
);
}
}
// Stateful Widget
class CounterWidget extends StatefulWidget {
const CounterWidget({Key? key}) : super(key: key);
@override
State<CounterWidget> createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<CounterWidget> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Counter: $_counter'),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('Increment'),
),
],
);
}
}
// Layout
class UserListScreen extends StatelessWidget {
final List<User> users;
const UserListScreen({Key? key, required this.users}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Users'),
actions: [
IconButton(
icon: Icon(Icons.add),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => AddUserScreen()),
),
),
],
),
body: ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return UserCard(user: users[index]);
},
),
);
}
}
状態管理 (Provider)
import 'package:provider/provider.dart';
// State class
class UserProvider extends ChangeNotifier {
List<User> _users = [];
List<User> get users => _users;
Future<void> fetchUsers() async {
_users = await api.getUsers();
notifyListeners();
}
void addUser(User user) {
_users.add(user);
notifyListeners();
}
void removeUser(String id) {
_users.removeWhere((user) => user.id == id);
notifyListeners();
}
}
// Setup provider
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => UserProvider()),
ChangeNotifierProvider(create: (_) => AuthProvider()),
],
child: MyApp(),
),
);
}
// Consume provider
class UserList extends StatelessWidget {
@override
Widget build(BuildContext context) {
final userProvider = Provider.of<UserProvider>(context);
return ListView.builder(
itemCount: userProvider.users.length,
itemBuilder: (context, index) {
final user = userProvider.users[index];
return ListTile(
title: Text(user.name),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => userProvider.removeUser(user.id),
),
);
},
);
}
}
// Consumer widget
class UserCounter extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<UserProvider>(
builder: (context, userProvider, child) {
return Text('Total users: ${userProvider.users.length}');
},
);
}
}
ナビゲーション
// Basic navigation
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetailScreen()),
);
// Named routes
MaterialApp(
routes: {
'/': (context) => HomeScreen(),
'/details': (context) => DetailScreen(),
'/settings': (context) => SettingsScreen(),
},
);
Navigator.pushNamed(context, '/details');
// Pass arguments
Navigator.pushNamed(
context,
'/details',
arguments: {'userId': '123'},
);
// Get arguments
final args = ModalRoute.of(context)!.settings.arguments as Map;
// Return data
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (_) => SelectionScreen()),
);
// Pop with result
Navigator.pop(context, selectedValue);
HTTP と API
import 'package:http/http.dart' as http;
import 'dart:convert';
class ApiService {
final String baseUrl = 'https://api.example.com';
Future<List<User>> fetchUsers() async {
final response = await http.get(Uri.parse('$baseUrl/users'));
if (response.statusCode == 200) {
final List<dynamic> data = json.decode(response.body);
return data.map((json) => User.fromJson(json)).toList();
} else {
throw Exception('Failed to load users');
}
}
Future<User> createUser(User user) async {
final response = await http.post(
Uri.parse('$baseUrl/users'),
headers: {'Content-Type': 'application/json'},
body: json.encode(user.toJson()),
);
if (response.statusCode == 201) {
return User.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to create user');
}
}
}
// Model with JSON serialization
class User {
final String id;
final String name;
final String email;
User({required this.id, required this.name, required this.email});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'],
email: json['email'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'email': email,
};
}
}
ベストプラクティス
Dart
- 可能な場合は const コンストラクタを使用する
- Null 安全性を活用する
- 不変値に final を使用する
- .then() よりも async/await を優先する
- ユーティリティ メソッド用に拡張機能を使用する
- Effective Dart ガイドラインに従う
Flutter
- ウィジェットを小さく焦点を絞った状態に保つ
- 最適化のために const ウィジェットを使用する
- ツリー全体の再構築を避ける
- 適切な状態管理を実装する
- エラーを適切に処理する
- ウィジェットを徹底的にテストする
- 必要に応じてキーを使用する
パフォーマンス
- 長いリストには ListView.builder を使用する
- ページネーションを実装する
- ネットワーク画像をキャッシュする
- ウィジェットの再構築を最小限にする
- const コンストラクタを使用する
- アプリケーション パフォーマンスをプロファイリングする
- リソースを遅延ロードする
アンチパターン
❌ 大規模なウィジェット ツリー ❌ StatelessWidget での状態 ❌ コントローラーの破棄漏れ ❌ Null 安全性を無視する ❌ UI での同期 I/O ❌ エラー処理なし ❌ ハードコードされた文字列
リソース
- Dart: https://dart.dev/
- Flutter: https://flutter.dev/
- Pub.dev: https://pub.dev/
- Flutter Widget Catalog: https://flutter.dev/docs/development/ui/widgets
- Effective Dart: https://dart.dev/guides/language/effective-dart
ライセンス: Apache-2.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- personamanagmentlayer
- ライセンス
- Apache-2.0
- 最終更新
- 不明
Source: https://github.com/personamanagmentlayer/pcl / ライセンス: Apache-2.0
関連スキル
superfluid
Superfluidプロトコルおよびそのエコシステムに関するナレッジベースです。Superfluidについて情報を検索する際は、ウェブ検索の前にこちらを参照してください。対応キーワード:Superfluid、CFA、GDA、Super App、Super Token、stream、flow rate、real-time balance、pool(member/distributor)、IDA、sentinels、liquidation、TOGA、@sfpro/sdk、semantic money、yellowpaper、whitepaper
civ-finish-quotes
実質的なタスクが真に完了した際に、文明風の儀式的な引用句を追加します。ユーザーやエージェントが機能追加、リファクタリング、分析、設計ドキュメント、プロセス改善、レポート、執筆タスクといった実際の成果物を完成させるときに、明示的な依頼がなくても使用します。短い返信や小さな修正、未完成の作業には適用しません。
nookplot
Base(Ethereum L2)上のAIエージェント向け分散型調整ネットワークです。エージェントがオンチェーンアイデンティティを登録する、コンテンツを公開する、他のエージェントにメッセージを送る、マーケットプレイスで専門家を雇う、バウンティを投稿・請求する、レピュテーションを構築する、共有プロジェクトで協業する、リサーチチャレンジを解くことでNOOKをマイニングする、キュレーションされたナレッジを備えたスタンドアロンオンチェーンエージェントをデプロイする、またはアグリーメントとリワードで収益を得る場合に利用できます。エージェントネットワーク、エージェント調整、分散型エージェント、NOOKトークン、マイニングチャレンジ、ナレッジバンドル、エージェントレピュテーション、エージェントマーケットプレイス、ERC-2771メタトランザクション、Prepare-Sign-Relay、AgentFactory、またはNookplotが言及された場合にトリガーされます。
web3-polymarket
Polygon上でのPolymarket予測市場取引統合です。認証機能(L1 EIP-712、L2 HMAC-SHA256、ビルダーヘッダー)、注文発注(GTC/GTD/FOK/FAK、バッチ、ポストオンリー、ハートビート)、市場データ(Gamma API、Data API、オーダーブック、サブグラフ)、WebSocketストリーミング(市場・ユーザー・スポーツチャネル)、CTF操作(分割、統合、償却、ネガティブリスク)、ブリッジ機能(入金、出金、マルチチェーン)、およびガスレスリレイトランザクションに対応しています。AIエージェント、自動マーケットメーカー、予測市場UI、またはPolygraph上のPolymarketと統合するアプリケーション構築時に活用できます。
ethskills
Ethereum、EVM、またはブロックチェーン関連のリクエストに対応します。スマートコントラクト、dApps、ウォレット、DeFiプロトコルの構築、監査、デプロイ、インタラクションに適用されます。Solidityの開発、コントラクトアドレス、トークン規格(ERC-20、ERC-721、ERC-4626など)、Layer 2ネットワーク(Base、Arbitrum、Optimism、zkSync、Polygon)、Uniswap、Aave、Curveなどのプロトコルとの統合をカバーします。ガスコスト、コントラクトのデシマル設定、オラクルセキュリティ、リエントランシー、MEV、ブリッジング、ウォレット管理、オンチェーンデータの取得、本番環境へのデプロイ、プロトコル進化(EIPライフサイクル、フォーク追跡、今後の変更予定)といったトピックを含みます。
xxyy-trade
このスキルは、ユーザーが「トークン購入」「トークン売却」「トークンスワップ」「暗号資産取引」「取引ステータス確認」「トランザクション照会」「トークンスキャン」「フィード」「チェーン監視」「トークン照会」「トークン詳細」「トークン安全性確認」「ウォレット一覧表示」「マイウォレット」「AIスキャン」「自動スキャン」「ツイートスキャン」「オンボーディング」「IP確認」「IPホワイトリスト」「トークン発行」「自動売却」「損切り」「利益確定」「トレーリングストップ」「保有者」「トップホルダー」「KOLホルダー」などをリクエストした場合、またはSolana/ETH/BSC/BaseチェーンでXXYYを経由した取引について言及した場合に使用します。XXYY Open APIを通じてオンチェーン取引とデータ照会を実現します。