flutter
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseFlutter
Flutter
Flutter is Google's UI toolkit for building natively compiled applications for mobile, web, and desktop from a single codebase. It uses the Dart programming language and the Skia/Impeller graphics engine to render high-performance, pixel-perfect UIs.
Flutter是谷歌推出的UI工具包,可通过单一代码库构建原生编译的移动、网页和桌面应用。它采用Dart编程语言以及Skia/Impeller图形引擎,以渲染高性能、像素级完美的UI。
When to Use
适用场景
- Building high-performance Android and iOS apps with a single codebase.
- Creating custom, branded UI designs that need to look identical across platforms.
- Developing prototypes or MVPs quickly with Hot Reload.
- needing a solution that compiles to native code (ARM/x86) and WebAssembly.
- 通过单一代码库构建高性能Android和iOS应用
- 创建需要在各平台保持视觉一致的自定义品牌UI设计
- 借助Hot Reload快速开发原型或最小可行产品(MVP)
- 需要可编译为原生代码(ARM/x86)和WebAssembly的解决方案
Quick Start
快速开始
dart
// main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
void main() {
runApp(const MyApp());
}
// Router configuration
final _router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomePage(),
),
],
);
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => CounterCubit(),
child: MaterialApp.router(
routerConfig: _router,
theme: ThemeData(useMaterial3: true, colorSchemeSeed: Colors.blue),
),
);
}
}
// Bloc/Cubit Logic
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
Widget build(BuildContext context) {
// Access state via context.read/watch or BlocBuilder
final count = context.select((CounterCubit cubit) => cubit.state);
return Scaffold(
appBar: AppBar(title: const Text('Flutter & Bloc')),
body: Center(
child: Text(
'Count: $count',
style: Theme.of(context).textTheme.headlineMedium,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => context.read<CounterCubit>().increment(),
child: const Icon(Icons.add),
),
);
}
}dart
// main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
void main() {
runApp(const MyApp());
}
// 路由配置
final _router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomePage(),
),
],
);
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => CounterCubit(),
child: MaterialApp.router(
routerConfig: _router,
theme: ThemeData(useMaterial3: true, colorSchemeSeed: Colors.blue),
),
);
}
}
// Bloc/Cubit 逻辑
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
Widget build(BuildContext context) {
// 通过context.read/watch或BlocBuilder访问状态
final count = context.select((CounterCubit cubit) => cubit.state);
return Scaffold(
appBar: AppBar(title: const Text('Flutter & Bloc')),
body: Center(
child: Text(
'Count: $count',
style: Theme.of(context).textTheme.headlineMedium,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => context.read<CounterCubit>().increment(),
child: const Icon(Icons.add),
),
);
}
}Core Concepts
核心概念
Widget Tree & Element Tree
组件树与元素树
Flutter uses a reactive style where the UI is built from a tree of immutable Widgets.
- Widget: A configuration for an Element. Immutable description of part of the UI.
- Element: An instantiation of a Widget at a particular location in the tree. Mutable manager of state and lifecycle.
- RenderObject: The actual object that gets painted on the screen.
Flutter采用响应式风格,UI由不可变的Widget树构建而成。
- Widget:Element的配置信息,是UI某一部分的不可变描述
- Element:Widget在树中特定位置的实例,是状态和生命周期的可变管理器
- RenderObject:实际绘制在屏幕上的对象
State Management (Bloc)
状态管理(Bloc)
Modern Flutter apps often use the Bloc (Business Logic Component) pattern for separation of concerns and predictable state.
- Events: Inputs to the Bloc (e.g., button pressed).
- States: Outputs from the Bloc (e.g., loading, data loaded).
- Bloc/Cubit: The class that receives events and emits new states.
- BlocBuilder: Widget that rebuilds in response to new states.
现代Flutter应用通常使用Bloc(业务逻辑组件)模式来实现关注点分离和可预测的状态管理。
- Events:Bloc的输入(如按钮点击)
- States:Bloc的输出(如加载中、数据已加载)
- Bloc/Cubit:接收事件并发出新状态的类
- BlocBuilder:响应新状态而重建的组件
Asynchronous Programming (Isolates)
异步编程(Isolates)
Dart is single-threaded but event-driven. Heavy computations should be moved to background Isolates to avoid blocking the UI thread (jank).
Dart是单线程但基于事件驱动的语言。繁重的计算任务应移至后台Isolates中执行,以避免阻塞UI线程(导致卡顿)。
Common Patterns
常见模式
Feature-First Architecture
功能优先架构
Organize files by feature rather than by layer.
text
lib/
src/
features/
auth/
data/
domain/
presentation/
bloc/
views/
products/
shared/
components/
constants/
app.dart
main.dart按功能而非层级组织文件。
text
lib/
src/
features/
auth/
data/
domain/
presentation/
bloc/
views/
products/
shared/
components/
constants/
app.dart
main.dartClean Architecture with Repositories
结合仓库模式的整洁架构
- Data Layer: Repositories, API clients (Dio/Http), DTOs.
- Domain Layer: Entities, business logic (pure Dart).
- Presentation Layer: Widgets, Blocs/Cubits.
- 数据层:仓库、API客户端(Dio/Http)、数据传输对象(DTO)
- 领域层:实体、业务逻辑(纯Dart实现)
- 表示层:Widget、Bloc/Cubit
Best Practices
最佳实践
Do:
- Use constructors everywhere possible to optimize rebuilds.
const - Use for deep linking and declarative navigation.
GoRouter - Use to separate business logic from UI.
flutter_bloc - Use and
ThemeDatafor consistent styling.TextTheme
Don't:
- Don't put complex logic inside methods.
build() - Don't misuse for complex global state.
setState - Don't block the main thread; use for heavy JSON parsing or calculations.
compute()
建议:
- 尽可能在所有地方使用构造函数,以优化重建性能
const - **使用**实现深度链接和声明式导航
GoRouter - **使用**分离业务逻辑与UI
flutter_bloc - **使用**和
ThemeData实现一致的样式TextTheme
不建议:
- 不要在方法中放置复杂逻辑
build() - 不要为复杂全局状态滥用
setState - 不要阻塞主线程;对于繁重的JSON解析或计算,使用
compute()
Troubleshooting
故障排查
| Error | Cause | Solution |
140: | :--------------------------------------------- | :--------------------------------------------- | :----------------------------------------------------------- |
141: | | Content is too wide/tall for the parent. | Wrap in , , or . |
142: | | Reading a Bloc without a provider up the tree. | Ensure wraps the widget trying to access it. |
143: | | Accessing a variable before assignment. | Ensure generic initialization or use nullable types locally. |
144: | | ListView inside Column without constraints. | Wrap ListView in or . |
RenderFlex overflowed by ... pixelsExpandedFlexibleSingleChildScrollViewProviderNotFoundExceptionBlocProviderLateInitializationErrorlateVertical viewport was given unbounded heightExpandedSizedBox| 错误 | 原因 | 解决方案 |
|---|---|---|
| 内容对于父容器来说过宽/过高 | 将内容包裹在 |
| 在未向上查找树中存在的Provider的情况下读取Bloc | 确保 |
| 在赋值前访问了 | 确保通用初始化,或在本地使用可空类型 |
| Column中的ListView没有约束 | 将ListView包裹在 |