Flutter 知识点

Flutter:一个移动应用开发框架,它使用 Dart、C++、Skia 开发,对外提供了完全不依赖系统平台的 Widget 的能力,只通过自绘图形的方式工作,具有极其优秀的跨平台性。目前已经支持了 iOS、Android、Fuchsia。

macOS 下,安卓模拟器的进程名为:sdkqemu-system-i386,可在任务管理器强行关闭。

如果提示:Please configure Android SDK,需要将 ANDROID_HOME 环境变量设置为相应的 SDK 安装目录

构建UI界面的逻辑在build方法中

Scaffold 是Material库中提供的页面脚手架,它包含导航栏和Body以及FloatingActionButton(如果需要的话)

路由(Route)在Android中通常指一个Activity,在iOS中指一个ViewController。

在原生开发中,Android使用Gradle来管理依赖,iOS用Cocoapods或Carthage来管理依赖。

而 Flutter 使用配置文件 pubspec.yaml(位于项目根目录)来管理第三方依赖包。

在构建期间,Flutter将asset放置到称为 asset bundle 的特殊存档中,应用程序可以在运行时读取它们(但不能修改)。

声明分辨率相关的图片 assets:

AssetImage 可以将asset的请求逻辑映射到最接近当前设备像素比例(dpi)的asset。为了使这种映射起作用,必须根据特定的目录结构来保存asset。

注意,AssetImage 并非是一个widget, 它实际上是一个ImageProvider,有些时候你可能期望直接得到一个显示图片的widget,那么你可以使用Image.asset()方法。

依赖包中的资源图片

要加载依赖包中的图像,必须给AssetImage提供package参数。

例如,假设您的应用程序依赖于一个名为“my_icons”的包,它具有如下目录结构:

…/pubspec.yaml
…/icons/heart.png
…/icons/1.5x/heart.png
…/icons/2.0x/heart.png
…etc.

然后加载图像,使用:

new AssetImage('icons/heart.png', package: 'my_icons')

new Image.asset('icons/heart.png', package: 'my_icons')

注意:包在使用本身的资源时也应该加上package参数来获取。

Dart分析器大量使用了代码中的类型注释来帮助追踪问题。我们鼓励您在任何地方使用它们(避免var、无类型的参数、无类型的列表文字等),因为这是追踪问题的最快的方式。

可以使用 debugger() 语句插入编程式断点。要使用这个,你必须添加 import 'dart:developer'; 到相关文件顶部;debugger()语句采用一个可选when参数。

微任务通常来源于Dart内部,并且微任务非常少。

值得注意的是,我们可以通过Future.microtask(…)方法向微任务队列插入一个任务。

在事件循环中,当某个任务发生异常并没有被捕获时,程序并不会退出,而直接导致的结果是当前任务的后续代码就不会被执行了,也就是说一个任务中的异常是不会影响其它任务执行的。

Flutter 中真正代表屏幕上显示元素的类是 Element,Widget 只是 Element 的配置数据。并且一个Widget可以对应多个Element。

Key: 这个key属性类似于React/Vue中的key,主要的作用是决定是否在下一次build时复用旧的widget,决定的条件在canUpdate()方法中。

didChangeDependencies()、didUpdateWidget()

  1. didChangeDependencies():当State对象的依赖发生变化时会被调用;例如:在之前build() 中包含了一个InheritedWidget,然后在之后的build() 中InheritedWidget发生了变化,那么此时InheritedWidget的子widget的didChangeDependencies()回调都会被调用。典型的场景是当系统语言Locale或应用主题改变时,Flutter framework会通知widget调用此回调。
  2. didUpdateWidget():在widget重新构建时,Flutter framework会调用Widget.canUpdate来检测Widget树中同一位置的新旧节点,然后决定是否需要更新,如果Widget.canUpdate返回true则会调用此回调。正如之前所述,Widget.canUpdate会在新旧widget的key和runtimeType同时相等时会返回true,也就是说在在新旧widget的key和runtimeType同时相等时didUpdateWidget()就会被调用。

deactivate()、dispose()

  1. deactivate():当State对象从树中被移除时,会调用此回调。在一些场景下,Flutter framework会将State对象重新插到树中,如包含此State对象的子树在树的一个位置移动到另一个位置时(可以通过GlobalKey来实现)。如果移除后没有重新插入到树中则紧接着会调用dispose()方法。
  2. dispose():当State对象从树中被永久移除时调用;通常在此回调中释放资源。

Flutter提供了一套丰富、强大的基础widget,在基础widget库之上Flutter又提供了一套Material风格(Android默认的视觉风格)和一套Cupertino风格(iOS视觉风格)的widget库。要使用基础widget库,需要先导入:

import 'package:flutter/widgets.dart';

由于Material和Cupertino都是在基础widget库之上的,所以如果你的应用中引入了这两者之一,则不需要再引入flutter/widgets.dart了,因为它们内部已经引入过了。

基础widget

  1. Text:该 widget 可让您创建一个带格式的文本。
  2. Row、 Column: 这些具有弹性空间的布局类Widget可让您在水平(Row)和垂直(Column)方向上创建灵活的布局。其设计是基于web开发中的Flexbox布局模型。
  3. Stack: 取代线性布局 (译者语:和Android中的FrameLayout相似),Stack允许子 widget 堆叠, 你可以使用 Positioned 来定位他们相对于Stack的上下左右四条边的位置。Stacks是基于Web开发中的绝对定位(absolute positioning )布局模型设计的。
  4. Container: Container 可让您创建矩形视觉元素。container 可以装饰一个BoxDecoration, 如 background、一个边框、或者一个阴影。 Container 也可以具有边距(margins)、填充(padding)和应用于其大小的约束(constraints)。另外, Container可以使用矩阵在三维空间中对其进行变换。

Text

  1. textAlign:文本的对齐方式;可以选择左对齐、右对齐还是居中。注意,对齐的参考系是Text widget本身。本例中虽然是指定了居中对齐,但因为Text文本内容宽度不足一行,Text的宽度和文本内容长度相等,那么这时指定对齐方式是没有意义的,只有Text宽度大于文本内容长度时指定此属性才有意义。
  2. textScaleFactor:代表文本相对于当前字体大小的缩放因子,相对于去设置文本的样式style属性的fontSize,它是调整字体大小的一个快捷方式。该属性的默认值可以通过MediaQueryData.textScaleFactor获得,如果没有MediaQuery,那么会默认值将为1.0。
  3. height:该属性用于指定行高,但它并不是一个绝对值,而是一个因子,具体的行高等于fontSize*height。
  4. fontSize:该属性和Text的textScaleFactor都用于控制字体大小。但是有两个主要区别:
  • fontSize可以精确指定字体大小,而textScaleFactor只能通过缩放比例来控制。
  • textScaleFactor主要是用于系统字体大小设置改变时对Flutter应用字体进行全局调整,而fontSize通常用于单个文本。

在Flutter中使用字体分两步完成。首先在pubspec.yaml中声明它们,以确保它们会打包到应用程序中。然后通过TextStyle属性使用字体。

按钮:有一个onPressed属性来设置点击回调,当按钮按下时会执行该回调,如果不提供该回调则按钮会处于禁用状态,禁用状态不响应用户点击。

使用自定义字体图标:在Flutter中,使用iconfont.cn上ttf格式的字体文件即可

容器的大小可以通过width、height属性来指定,也可以通过constraints来指定,如果同时存在时,width、height优先。实际上Container内部会根据width、height来生成一个constraints。

Material Design 设计规范中有些是不能自定义的,如导航栏高度,ThemeData只包含了可自定义部分。

如果不想让某个子树响应PointerEvent的话,我们可以使用IgnorePointer和AbsorbPointer,这两个Widget都能阻止子树接收指针事件,不同之处在于AbsorbPointer本身会参与命中测试,而IgnorePointer本身不会参与,这就意味着AbsorbPointer本身是可以接收指针事件的(但其子树不行),而IgnorePointer不可以。

GestureDetector内部是使用一个或多个GestureRecognizer来识别各种手势的,而GestureRecognizer的作用就是通过Listener来将原始指针事件转换为语义手势,GestureDetector直接可以接收一个子Widget。GestureRecognizer是一个抽象类,一种手势的识别器对应一个GestureRecognizer的子类。

在Flutter中自定义Widget有三种方式:通过组合其它Widget、自绘和实现RenderObject。

自绘:Flutter中提供了CustomPaint和Canvas供我们自绘UI外观。

际上Flutter提供的所有Widget最终都是调用Canvas绘制出来的。

通过HttpClient设置的header,对整个httpClient都生效;而通过HttpClientRequest设置的header,只对当前请求生效。

与Future返回单个异步响应不同,Stream类可以随着时间推移传递很多事件。

运行flutter build apk后,打包文件的路径:build/app/outputs/apk/release/app-release.apk

上一篇:R用户的福音︱TensorFlow:TensorFlow的R接口


下一篇:[C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例