-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs(zh-cn): add
flutter-counter.mdx
(#4244)
Co-authored-by: Felix Angelov <[email protected]>
- Loading branch information
Showing
1 changed file
with
187 additions
and
0 deletions.
There are no files selected for viewing
187 changes: 187 additions & 0 deletions
187
docs/src/content/docs/zh-cn/tutorials/flutter-counter.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
--- | ||
title: Flutter 计数器 | ||
description: 关于如何使用 bloc 构建 Flutter 计数器应用程序的深入指南。 | ||
sidebar: | ||
order: 1 | ||
--- | ||
|
||
import RemoteCode from '~/components/tutorials/RemoteCode.astro'; | ||
import FlutterCreateSnippet from '~/components/tutorials/flutter-counter/FlutterCreateSnippet.astro'; | ||
import FlutterPackagesGetSnippet from '~/components/tutorials/flutter-counter/FlutterPackagesGetSnippet.astro'; | ||
|
||
![初级](https://img.shields.io/badge/level-beginner-green.svg) | ||
|
||
在下面的教程中,我们将使用 Bloc 库在 Flutter 中构建一个计数器。 | ||
|
||
![demo](~/assets/tutorials/flutter-counter.gif) | ||
|
||
## 关键主题 | ||
|
||
- 使用 [BlocObserver](/zh-cn/bloc-concepts#blocobserver) 观察状态变更。 | ||
- [BlocProvider](/zh-cn/flutter-bloc-concepts#blocprovider),为子组件提供 bloc 的 Flutter 部件。 | ||
- [BlocBuilder](/zh-cn/flutter-bloc-concepts#blocbuilder),用于响应新状态来构建小部件的 Flutter 部件。 | ||
- 用 Cubit 替代 Bloc。[有什么不同?](/zh-cn/bloc-concepts#cubit-和-bloc-对比)。 | ||
- 使用 [context.read](/zh-cn/flutter-bloc-concepts#contextread) 添加事件。 | ||
|
||
## 设置 | ||
|
||
我们从创建一个全新的 Flutter 项目开始 | ||
|
||
<FlutterCreateSnippet /> | ||
|
||
用下面的代码替换 `pubspec.yaml` 的内容: | ||
|
||
<RemoteCode | ||
url="https://raw.githubusercontent.com/felangel/bloc/master/examples/flutter_counter/pubspec.yaml" | ||
title="pubspec.yaml" | ||
/> | ||
|
||
然后安装所有的依赖 | ||
|
||
<FlutterPackagesGetSnippet /> | ||
|
||
## 项目结构 | ||
|
||
``` | ||
├── lib | ||
│ ├── app.dart | ||
│ ├── counter | ||
│ │ ├── counter.dart | ||
│ │ ├── cubit | ||
│ │ │ └── counter_cubit.dart | ||
│ │ └── view | ||
│ │ ├── counter_page.dart | ||
│ │ ├── counter_view.dart | ||
│ │ └── view.dart | ||
│ ├── counter_observer.dart | ||
│ └── main.dart | ||
├── pubspec.lock | ||
├── pubspec.yaml | ||
``` | ||
|
||
这个应用采用了功能驱动的目录结构。这种项目结构以便于我们按照独立的功能对项目进行扩展。这个示例项目里只有一个功能(计数器),但是在更加复杂的应用里我们可以包含数以百计的功能。 | ||
|
||
## BlocObserver | ||
|
||
我们要做的第一件事是看看如何创建一个 `BlocObserver` 来观察应用里所有的状态变更。 | ||
|
||
我们先创建一个 `lib/counter_observer.dart`: | ||
|
||
<RemoteCode | ||
url="https://raw.githubusercontent.com/felangel/bloc/master/examples/flutter_counter/lib/counter_observer.dart" | ||
title="lib/counter_observer.dart" | ||
/> | ||
|
||
目前,我们仅重写了 `onChange` 来查看所有发生的状态变更。 | ||
|
||
:::note | ||
`Bloc` 和 `Cubit` 的 `onChange` 工作方式是相同的。 | ||
::: | ||
|
||
## main.dart | ||
|
||
下一步,我们替换 `lib/main.dart` 的代码如下: | ||
|
||
<RemoteCode | ||
url="https://raw.githubusercontent.com/felangel/bloc/master/examples/flutter_counter/lib/main.dart" | ||
title="lib/main.dart" | ||
/> | ||
|
||
我们初始化了我们创建的 `CounterObserver` 并且在 `runApp` 里添加了 `CounterApp` 组件。 | ||
|
||
## Counter App | ||
|
||
创建一个 `lib/app.dart`: | ||
|
||
`CounterApp` 是一个 `MaterialApp` 并且指定了 `CounterPage` 作为主页。 | ||
|
||
<RemoteCode | ||
url="https://raw.githubusercontent.com/felangel/bloc/master/examples/flutter_counter/lib/app.dart" | ||
title="lib/app.dart" | ||
/> | ||
|
||
:::note | ||
我们扩展了 `MaterialApp` 因为 `CounterApp` _是_ 一个 `MaterialApp`。在大多数情况下,我们会创建 `StatelessWidget` 或者 `StatefulWidget` 实例并且在 `build` 里进行组合。但是在这里没有部件需要组合,所以最简单的方式就是直接扩展 `MaterialApp`。 | ||
::: | ||
|
||
接下来咱们看看 `CounterPage` ! | ||
|
||
## Counter Page | ||
|
||
创建 `lib/counter/view/counter_page.dart` 如下: | ||
|
||
`CounterPage` 部件负责创建 `CounterCubit` (下面会讲到)并且提供给 `CounterView`。 | ||
|
||
<RemoteCode | ||
url="https://raw.githubusercontent.com/felangel/bloc/master/examples/flutter_counter/lib/counter/view/counter_page.dart" | ||
title="lib/counter/view/counter_page.dart" | ||
/> | ||
|
||
:::note | ||
将 `Cubit` 的创建和消费分开并解耦非常重要,这样可以让代码更加的易于测试和重用。 | ||
::: | ||
|
||
## Counter Cubit | ||
|
||
创建 `lib/counter/cubit/counter_cubit.dart` 如下: | ||
|
||
`CounterCubit` 会公开以下方法: | ||
|
||
- `increment`: 当前状态 +1 | ||
- `decrement`: 当前状态 -1 | ||
|
||
`CounterCubit` 管理的是 `int` 型的状态,初始值为 `0`。 | ||
|
||
<RemoteCode | ||
url="https://raw.githubusercontent.com/felangel/bloc/master/examples/flutter_counter/lib/counter/cubit/counter_cubit.dart" | ||
title="lib/counter/cubit/counter_cubit.dart" | ||
/> | ||
|
||
:::tip | ||
使用 [VSCode 插件](https://marketplace.visualstudio.com/items?itemName=FelixAngelov.bloc) 或者 [IntelliJ 插件](https://plugins.jetbrains.com/plugin/12129-bloc) 可以自动创建新的 cubits。 | ||
::: | ||
|
||
接下来,我们看看负责消费并且与 `CounterCubit` 进行交互的 `CounterView`。 | ||
|
||
## Counter View | ||
|
||
创建 `lib/counter/view/counter_view.dart` 如下: | ||
|
||
`CounterView` 负责渲染当前的数值,以及两个 FloatingActionButtons 来负责增/减计数。 | ||
|
||
<RemoteCode | ||
url="https://raw.githubusercontent.com/felangel/bloc/master/examples/flutter_counter/lib/counter/view/counter_view.dart" | ||
title="lib/counter/view/counter_view.dart" | ||
/> | ||
|
||
`BlocBuilder` 用来包装 `Text` 部件,这样 `CounterCubit` 任何的状态变化都会更新文本。此外, `context.read<CounterCubit>()` 用于查找最近的 `CounterCubit` 实例。 | ||
|
||
:::note | ||
只有 `Text` 部件被包装在 `BlocBuilder` 里,因为它是 `CounterCubit` 状态变更时需要更新的唯一部件。避免包装不需要根据状态变更重新构建的部件。 | ||
::: | ||
|
||
## Barrel | ||
|
||
创建 `lib/counter/view/view.dart`: | ||
|
||
添加 `view.dart` 来导出所有 counter 视图的公共部分。 | ||
|
||
<RemoteCode | ||
url="https://raw.githubusercontent.com/felangel/bloc/master/examples/flutter_counter/lib/counter/view/view.dart" | ||
title="lib/counter/view/view.dart" | ||
/> | ||
|
||
创建 `lib/counter/counter.dart`: | ||
|
||
添加 `counter.dart` 来导出 counter 功能的所有公共部分。 | ||
|
||
<RemoteCode | ||
url="https://raw.githubusercontent.com/felangel/bloc/master/examples/flutter_counter/lib/counter/counter.dart" | ||
title="lib/counter/counter.dart" | ||
/> | ||
|
||
以上就是全部!我们将业务逻辑层从展现层种分离了出来。 `CounterView` 不知道用户按下按钮以后会发生什么;它只是通知 `CounterCubit`。此外,`CounterCubit` 也不知道状态(计数器的值)发生了什么;它只是响应调用的方法发出新状态。 | ||
|
||
我们可以运行 `flutter run` 来在设备或者模拟器上查看运行的效果。 | ||
|
||
可以在 [这里](https://github.com/felangel/Bloc/tree/master/examples/flutter_counter) 找到这个例子的完整代码(包括单元和部件测试)。 |