Skip to content

Commit 960153a

Browse files
committed
更新内容
2 parents 6a2b233 + 1670f79 commit 960153a

File tree

13 files changed

+67
-27
lines changed

13 files changed

+67
-27
lines changed

docs/chapter1/install_flutter.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,9 +470,9 @@ Could not Get **
470470
471471
#### Hot Reload 热重载失效问题
472472

473-
在给 `Terminal` 之类的终端模拟器设置代理之后,会导致Hot Reload重载失效,此时调用 **Save** (`cmd-s` / `ctrl-s`)将不会进行热重载,**热重载按钮** (带有闪电⚡️图标的按钮)也不会显示,将代理移除即可解决。
473+
在给 `Terminal` 之类的终端模拟器设置代理之后,会导致Hot Reload重载失效,此时调用 **Save** (`cmd-s` / `ctrl-s`)将不会进行热重载,**热重载按钮** (带有闪电⚡️图标的按钮)也不会显示,将代理移除即可解决。
474474

475-
另外,有些情况下热重载是不生效的,比如修改了`main`函数、修改了全局静态方法等,读者可以认为Hot Reload只会重新构建整个widget树,如果变动不在构建widget树的过程中,Hot Reload就不会起作用。
475+
另外,有些情况下热重载是不生效的,比如修改了`main`函数、修改了全局静态方法等,读者可以认为Hot Reload只会重新构建整个widget树,如果变动不在构建widget树的过程中,Hot Reload就不会起作用。
476476

477477

478478

docs/chapter1/mobile_development_intro.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,9 @@ Flutter是Google发布的一个用于创建跨平台、高性能移动应用的
220220

221221
现在,我们来和QT mobile做一个对比:
222222

223-
1. 生态从Github上来看,目前Flutter活跃用户正在高速增长。从Stackoverflow上提问来看,Flutter社区现在已经很庞大。Flutter的文档、资源也越来越丰富,开发过程中遇到的很多问题都可以在Stackoverflow或其github issue中找到答案。
224-
2. 技术支持现在Google正在大力推广Flutter,Flutter的作者中很多人都是来自Chromium团队,并且github上活跃度很高。另一个角度,从今年上半年Flutter频繁的版本发布也可以看出Google对Flutter的投入的资源不小,所以在官方技术支持这方面,大可不必担心。
225-
3. 开发效率Flutter的热重载可帮助开发者快速地进行测试、构建UI、添加功能并更快地修复错误。在iOS和Android模拟器或真机上可以实现毫秒级热重载,并且不会丢失状态。这真的很棒,相信我,如果你是一名原生开发者,体验了Flutter开发流后,很可能就不想重新回去做原生了,毕竟很少有人不吐槽原生开发的编译速度。
223+
1. 生态从Github上来看,目前Flutter活跃用户正在高速增长。从Stackoverflow上提问来看,Flutter社区现在已经很庞大。Flutter的文档、资源也越来越丰富,开发过程中遇到的很多问题都可以在Stackoverflow或其github issue中找到答案。
224+
2. 技术支持现在Google正在大力推广Flutter,Flutter的作者中很多人都是来自Chromium团队,并且github上活跃度很高。另一个角度,从今年上半年Flutter频繁的版本发布也可以看出Google对Flutter的投入的资源不小,所以在官方技术支持这方面,大可不必担心。
225+
3. 开发效率Flutter的热重载可帮助开发者快速地进行测试、构建UI、添加功能并更快地修复错误。在iOS和Android模拟器或真机上可以实现毫秒级热重载,并且不会丢失状态。这真的很棒,相信我,如果你是一名原生开发者,体验了Flutter开发流后,很可能就不想重新回去做原生了,毕竟很少有人不吐槽原生开发的编译速度。
226226

227227
基于以上三点,相信读者和笔者一样,Flutter未来如何,心中自有定论。到现在为止,我们已经对移动端开发技术有了一个全面的了解,接下来我们便要进入本书的主题,你准备好了吗!
228228

docs/chapter13/multi_languages_support.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ new MaterialApp(
4040
)
4141
```
4242

43-
基于`WidgetsAp`p的应用程序类似,只是不需要`GlobalMaterialLocalizations.delegate`。
43+
> 与`MaterialApp`类为入口的应用不同, 对基于`WidgetsApp`类为入口的应用程序进行国际化时,不需要`GlobalMaterialLocalizations.delegate`。
4444

4545
`localizationsDelegates`列表中的元素是生成本地化值集合的工厂。`GlobalMaterialLocalizations.delegate` 为Material 组件库提供的本地化的字符串和其他值,它可以使Material 组件支持多语言。 `GlobalWidgetsLocalizations.delegate`定义组件默认的文本方向,从左到右或从右到左,这是因为有些语言的阅读习惯并不是从左到右,比如如阿拉伯语就是从右向左的。
4646

docs/chapter2/first_flutter_app.md

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class _MyHomePageState extends State<MyHomePage> {
128128

129129
- `MyApp`类代表Flutter应用,它继承了 `StatelessWidget `类,这也就意味着应用本身也是一个widget。
130130

131-
- 在Flutter中,大多数东西都是widget(后同”组件“或”部件“),包括对齐(alignment)、填充(padding)和布局(layout)等,它们都是以widget的形式提供。
131+
- 在Flutter中,大多数东西都是widget(后同“组件”或“部件”),包括对齐(alignment)、填充(padding)和布局(layout)等,它们都是以widget的形式提供。
132132

133133
- Flutter在构建页面时,会调用组件的`build`方法,widget的主要工作是提供一个build()方法来描述如何构建UI界面(通常是通过组合、拼装其它基础widget)。
134134

@@ -153,7 +153,7 @@ class _MyHomePageState extends State<MyHomePage> {
153153
}
154154
```
155155

156-
`MyHomePage` 是Flutter应用的首页,它继承自`StatefulWidget`类,表示它是一个有状态的组件(Stateful widget)。关于Stateful widget我们将在第三章”Widget简介“一节自习介绍,现在我们只需简单认为有状态的组件(Stateful widget) 和无状态的组件(Stateless widget)有两点不同:
156+
`MyHomePage` 是Flutter应用的首页,它继承自`StatefulWidget`类,表示它是一个有状态的组件(Stateful widget)。关于Stateful widget我们将在第三章“Widget简介”一节仔细介绍,现在我们只需简单认为有状态的组件(Stateful widget) 和无状态的组件(Stateless widget)有两点不同:
157157

158158
1. Stateful widget可以拥有状态,这些状态在widget生命周期中是可以变的,而Stateless widget是不可变的。
159159

@@ -220,12 +220,52 @@ class _MyHomePageState extends State<MyHomePage> {
220220
}
221221
```
222222

223-
- `Scaffold` 是 Material组件库中提供的一个组件,它提供了默认的导航栏、标题和包含主屏幕widget树(后同”组件树“或”部件树“)的`body`属性。组件树可以很复杂。
223+
- `Scaffold` 是 Material组件库中提供的一个组件,它提供了默认的导航栏、标题和包含主屏幕widget树(后同“组件树”或“部件树”)的`body`属性。组件树可以很复杂。
224224
- `body`的组件树中包含了一个`Center` 组件,`Center` 可以将其子组件树对齐到屏幕中心。此例中, `Center` 子组件是一个`Column` 组件,`Column`的作用是将其所有子组件沿屏幕垂直方向依次排列; 此例中`Column`子组件是两个 `Text `,第一个`Text` 显示固定文本 “You have pushed the button this many times:”,第二个`Text` 显示`_counter`状态的数值。
225225
- `floatingActionButton`是页面右下角的带“+”的悬浮按钮,它的`onPressed`属性接受一个回调函数,代表它被点击后的处理器,本例中直接将`_incrementCounter`方法作为其处理函数。
226226

227227

228+
228229
现在,我们将整个计数器执行流程串起来:当右下角的`floatingActionButton`按钮被点击之后,会调用`_incrementCounter`方法。在`_incrementCounter`方法中,首先会自增`_counter`计数器(状态),然后`setState`会通知Flutter框架状态发生变化,接着,Flutter框架会调用`build`方法以新的状态重新构建UI,最终显示在设备屏幕上。
229230

230231

232+
#### 为什么要将build方法放在State中,而不是放在StatefulWidget中?
233+
234+
现在,我们回答之前提出的问题,为什么`build()`方法放在State(而不是`StatefulWidget`)中 ?这主要是为了提高开发的灵活性。如果将`build()`方法放在`StatefulWidget`中则会有两个问题:
235+
236+
- 状态访问不便
237+
238+
试想一下,如果我们的`StatefulWidget`有很多状态,而每次状态改变都要调用`build`方法,由于状态是保存在State中的,如果`build`方法在`StatefulWidget`中,那么`build`方法和状态分别在两个类中,那么构建时读取状态将会很不方便!试想一下,如果真的将`build`方法放在StatefulWidget中的话,由于构建用户界面过程需要依赖State,所以`build`方法将必须加一个`State`参数,大概是下面这样:
239+
240+
```dart
241+
Widget build(BuildContext context, State state){
242+
//state.counter
243+
...
244+
}
245+
```
246+
247+
这样的话就只能将State的所有状态声明为公开的状态,这样才能在State类外部访问状态!但是,将状态设置为公开后,状态将不再具有私密性,这就会导致对状态的修改将会变的不可控。但如果将`build()`方法放在State中的话,构建过程不仅可以直接访问状态,而且也无需公开私有状态,这会非常方便。
248+
249+
- 继承`StatefulWidget`不便
250+
251+
例如,Flutter中有一个动画widget的基类`AnimatedWidget`,它继承自`StatefulWidget`类。`AnimatedWidget`中引入了一个抽象方法`build(BuildContext context)`,继承自`AnimatedWidget`的动画widget都要实现这个`build`方法。现在设想一下,如果`StatefulWidget` 类中已经有了一个`build`方法,正如上面所述,此时`build`方法需要接收一个state对象,这就意味着`AnimatedWidget`必须将自己的State对象(记为_animatedWidgetState)提供给其子类,因为子类需要在其`build`方法中调用父类的`build`方法,代码可能如下:
252+
253+
```dart
254+
class MyAnimationWidget extends AnimatedWidget{
255+
@override
256+
Widget build(BuildContext context, State state){
257+
//由于子类要用到AnimatedWidget的状态对象_animatedWidgetState,
258+
//所以AnimatedWidget必须通过某种方式将其状态对象_animatedWidgetState
259+
//暴露给其子类
260+
super.build(context, _animatedWidgetState)
261+
}
262+
}
263+
```
264+
265+
这样很显然是不合理的,因为
266+
267+
1. `AnimatedWidget`的状态对象是`AnimatedWidget`内部实现细节,不应该暴露给外部。
268+
2. 如果要将父类状态暴露给子类,那么必须得有一种传递机制,而做这一套传递机制是无意义的,因为父子类之间状态的传递和子类本身逻辑是无关的。
269+
270+
综上所述,可以发现,对于`StatefulWidget`,将`build`方法放在State中,可以给开发带来很大的灵活性。
231271

docs/chapter2/flutter_app_debug.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
如果我们使用`flutter run`启动应用程序,那么当它运行时,我们可以打开Observatory工具的Web页面,例如Observatory默认监听[http://127.0.0.1:8100/](http://127.0.0.1:8100/),可以在浏览器中直接打开该链接。直接使用语句级单步调试器连接到您的应用程序。如果您使用的是IntelliJ,则还可以使用其内置的调试器来调试您的应用程序。
1515

16-
Observatory 同时支持分析、检查堆等。有关Observatory的更多信息请参考[Observatory 文档](https://dart-lang.github.io/observatory/).
16+
Observatory 同时支持分析、检查堆等。有关Observatory的更多信息请参考[Observatory 文档](https://dart-lang.github.io/observatory/)
1717

1818
如果您使用Observatory进行分析,请确保通过`--profile`选项来运行`flutter run`命令来运行应用程序。 否则,配置文件中将出现的主要问题将是调试断言,以验证框架的各种不变量(请参阅下面的“调试模式断言”)。
1919

@@ -144,7 +144,7 @@ I/flutter ( 6559): │ size: Size(411.4, 683.4)
144144

145145
最内部RenderPositionedBox再次松开约束,这次是将按钮中的文本居中。 在[`RenderParagraph`](https://docs.flutter.io/flutter/rendering/RenderParagraph-class.html)中基于它的内容来决定其大小。 如果您现在按照size链继续往下查看,您会看到文本的大小是如何影响其按钮的框的宽度的,它们都是根据孩子的尺寸自行调整大小。
146146

147-
另一种需要注意的是每个盒子描述的relayoutSubtreeRoot”部分,它告诉你有多少祖先以某种方式依赖于这个元素的大小。 因此,`RenderParagraph`有一个`relayoutSubtreeRoot=up8`,这意味着当它`RenderParagraph`被标及为dirty”时,它的八个祖先也必须被标记为dirty”,因为它们可能受到新尺寸的影响。
147+
另一种需要注意的是每个盒子描述的relayoutSubtreeRoot”部分,它告诉你有多少祖先以某种方式依赖于这个元素的大小。 因此,`RenderParagraph`有一个`relayoutSubtreeRoot=up8`,这意味着当它`RenderParagraph`被标及为dirty”时,它的八个祖先也必须被标记为dirty”,因为它们可能受到新尺寸的影响。
148148

149149
如果您编写自己的渲染对象,则可以通过覆盖[`debugFillProperties()`](https://docs.flutter.io/flutter/rendering/Layer/debugFillProperties.html)将信息添加到转储。 将[DiagnosticsProperty](https://docs.flutter.io/flutter/foundation/DiagnosticsProperty-class.html)对象作为方法的参数,并调用父类方法。
150150

@@ -264,7 +264,7 @@ Timeline.startSync('interesting function');
264264
Timeline.finishSync();
265265
```
266266

267-
然后打开你应用程序的Observatory timeline页面,在Recorded Streams”中选择Dart’复选框,并执行你想测量的功能。
267+
然后打开你应用程序的Observatory timeline页面,在Recorded Streams”中选择Dart’复选框,并执行你想测量的功能。
268268

269269
刷新页面将在Chrome的[跟踪工具](https://www.chromium.org/developers/how-tos/trace-event-profiling-tool)中显示应用按时间顺序排列的timeline记录。
270270

docs/chapter2/flutter_assets_mgr.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ flutter:
172172
173173
- Android
174174
175-
在Flutter项目的根目录中,导航到`.../android/app/src/main/res`目录,里面包含了各种资源文件夹(如`mipmap-hdpi`已包含占位符图像ic_launcher.png”,见图2-8)。 只需按照[Android开发人员指南](https://developer.android.com/guide/practices/ui_guidelines/icon_design_launcher.html#size)中的说明, 将其替换为所需的资源,并遵守每种屏幕密度(dpi)的建议图标大小标准。
175+
在Flutter项目的根目录中,导航到`.../android/app/src/main/res`目录,里面包含了各种资源文件夹(如`mipmap-hdpi`已包含占位符图像ic_launcher.png”,见图2-8)。 只需按照[Android开发人员指南](https://developer.android.com/guide/practices/ui_guidelines/icon_design_launcher.html#size)中的说明, 将其替换为所需的资源,并遵守每种屏幕密度(dpi)的建议图标大小标准。
176176
177177
![图2-8](../imgs/2-8.png)
178178

docs/chapter2/flutter_package_mgr.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 2.3 包管理
22

3-
在软件开放,很多时候有一些公共的库或SDK可能会被很多项目用到,因此,将这些代码单独抽到一个独立模块,然后哪个项目需要使用时再直接集成这个模块,便可大大提高开发效率。很多编程语言或开发工具都支持这种“模块共享”机制,如Java语言中这种独立模块会被打成一个jar包,Android中的aar包,Web开发中的npm包等。为了方便表述,我们将这种可共享的独立模块统一称为“包”( Package)。
3+
在软件开发中,很多时候有一些公共的库或SDK可能会被很多项目用到,因此,将这些代码单独抽到一个独立模块,然后哪个项目需要使用时再直接集成这个模块,便可大大提高开发效率。很多编程语言或开发工具都支持这种“模块共享”机制,如Java语言中这种独立模块会被打成一个jar包,Android中的aar包,Web开发中的npm包等。为了方便表述,我们将这种可共享的独立模块统一称为“包”( Package)。
44

55
一个APP在实际开发中往往会依赖很多包,而这些包通常都有交叉依赖关系、版本依赖等,如果由开发者手动来管理应用中的依赖包将会非常麻烦。因此,各种开发生态或编程语言官方通常都会提供一些包管理工具,比如在Android提供了Gradle来管理依赖,iOS用Cocoapods或Carthage来管理依赖,Node中通过npm等。而在Flutter开发中也有自己的包管理工具。本节我们主要介绍一下flutter如何使用配置文件`pubspec.yaml`(位于项目根目录)来管理第三方依赖包。
66

@@ -154,6 +154,6 @@ Pub(https://pub.dartlang.org/ )是Google官方的Dart Packages仓库,类
154154

155155
## 总结
156156

157-
本节介绍了Flutter中包管理、引用、下载的整体流程,我们将在后面的章节中介绍如果开发并发布我们自己的包
157+
本节介绍了Flutter中包管理、引用、下载的整体流程,我们将在后面的章节中介绍如何开发并发布我们自己的包
158158

159159

0 commit comments

Comments
 (0)