dart-expert

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Dart & Flutter Expert

Dart & Flutter 专业指南

Expert guidance for Dart programming, Flutter framework, mobile development, and cross-platform applications.
为Dart编程、Flutter框架、移动开发及跨平台应用提供专业指导。

Core Concepts

核心概念

Dart Language

Dart 语言特性

  • Strong typing with type inference
  • Async/await and Futures
  • Streams
  • Mixins and extensions
  • Null safety
  • Collections
  • 带类型推断的强类型系统
  • Async/await 与 Future
  • Stream 流
  • Mixin 与扩展
  • 空安全
  • 集合

Flutter Framework

Flutter 框架核心

  • Widgets (Stateless & Stateful)
  • State management (Provider, Riverpod, Bloc)
  • Navigation and routing
  • Material and Cupertino design
  • Responsive layouts
  • Platform integration
  • Widget(无状态与有状态)
  • 状态管理(Provider、Riverpod、Bloc)
  • 页面导航与路由
  • Material 与 Cupertino 设计规范
  • 响应式布局
  • 平台集成

Dart Fundamentals

Dart 基础语法

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++;
  }

  
  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)}';
}
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++;
  }

  
  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)}';
}

Async Programming

异步编程

dart
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();
  }
}
dart
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 Widgets

Flutter Widget 组件

dart
import 'package:flutter/material.dart';

// Stateless Widget
class UserCard extends StatelessWidget {
  final User user;

  const UserCard({Key? key, required this.user}) : super(key: key);

  
  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);

  
  State<CounterWidget> createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  
  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);

  
  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]);
        },
      ),
    );
  }
}
dart
import 'package:flutter/material.dart';

// Stateless Widget
class UserCard extends StatelessWidget {
  final User user;

  const UserCard({Key? key, required this.user}) : super(key: key);

  
  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);

  
  State<CounterWidget> createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  
  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);

  
  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]);
        },
      ),
    );
  }
}

State Management (Provider)

状态管理(Provider)

dart
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 {
  
  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 {
  
  Widget build(BuildContext context) {
    return Consumer<UserProvider>(
      builder: (context, userProvider, child) {
        return Text('Total users: ${userProvider.users.length}');
      },
    );
  }
}
dart
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 {
  
  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 {
  
  Widget build(BuildContext context) {
    return Consumer<UserProvider>(
      builder: (context, userProvider, child) {
        return Text('Total users: ${userProvider.users.length}');
      },
    );
  }
}

Navigation

页面导航

dart
// 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);
dart
// 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 and API

HTTP 与 API 交互

dart
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
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,
    };
  }
}

Best Practices

最佳实践

Dart

Dart

  • Use const constructors when possible
  • Leverage null safety
  • Use final for immutable values
  • Prefer async/await over .then()
  • Use extensions for utility methods
  • Follow Effective Dart guidelines
  • 尽可能使用const构造函数
  • 充分利用空安全特性
  • 用final声明不可变值
  • 优先使用async/await而非.then()
  • 用扩展实现工具方法
  • 遵循Effective Dart规范

Flutter

Flutter

  • Keep widgets small and focused
  • Use const widgets for optimization
  • Avoid rebuilding entire trees
  • Implement proper state management
  • Handle errors gracefully
  • Test widgets thoroughly
  • Use keys when needed
  • 保持Widget小巧且职责单一
  • 使用const Widget优化性能
  • 避免重建整个Widget树
  • 实现合理的状态管理
  • 优雅处理错误
  • 全面测试Widget
  • 必要时使用Key

Performance

性能优化

  • Use ListView.builder for long lists
  • Implement pagination
  • Cache network images
  • Minimize widget rebuilds
  • Use const constructors
  • Profile app performance
  • Lazy load resources
  • 长列表使用ListView.builder
  • 实现分页加载
  • 缓存网络图片
  • 减少Widget重建次数
  • 使用const构造函数
  • 分析应用性能
  • 懒加载资源

Anti-Patterns

反模式

❌ Large widget trees ❌ State in StatelessWidget ❌ Not disposing controllers ❌ Ignoring null safety ❌ Synchronous I/O in UI ❌ No error handling ❌ Hard-coded strings
❌ 庞大的Widget树 ❌ 在无状态Widget中存储状态 ❌ 未销毁控制器 ❌ 忽略空安全 ❌ 在UI线程执行同步I/O ❌ 无错误处理 ❌ 硬编码字符串

Resources

参考资源