原创

Flutter学习记录

Flutter学习记录

官网文档https://docs.flutter.cn/get-started

API地址https://api.dart.cn/

flutter实战 https://book.flutterchina.club/

一. Dart语言概览

官网文档地址

走一个初始化流程地址https://codelabs.developers.google.cn/codelabs/dart-patterns-records?hl=zh-cn#0

1. Dart概览

2. Dart简介

文档地址

1. 重要概念
  • 变量中可以放置的一切都是对象,每个对象都是的实例。偶数、函数和null都是对象。除了null(如果启用声音null安全),所有对象都继承自Object类。

    空安全是在Dart 2.12中引入的。使用空安全需要至少2.12的语言版本

  • 尽管Dart是强类型的,但类型注释是可选的,因为Dart可以推断类型。在var number = 101中,number被推断为int类型。

  • 如果启用null安全,变量不能包含null,除非你说可以。您可以通过在变量类型的末尾加上问号(?)来使变量为null。例如,int?类型的变量可能是整数,也可能是null。如果您知道表达式永远不会计算为null,但Dart不同意,您可以添加!来断言它不是null(如果是则抛出异常)。一个例子:int x = nullableButNotNullInt!

  • 当您想明确表示允许任何类型时,请使用类型Object?(如果您启用了空安全)、Object或(如果您必须将类型检查推迟到运行时)特殊类型dynamic

  • Dart支持泛型类型,如List<int>(整数列表)或List<Object>(任何类型的对象列表)。

  • Dart支持顶级函数(如main()),以及绑定到类或对象的函数(分别为静态实例方法)。您还可以在函数中创建函数(嵌套本地函数)。

  • 类似地,Dart支持顶级变量,以及绑定到类或对象的变量(静态和实例变量)。实例变量有时称为字段或属性。

  • 与Java不同,Dart没有关键字publicprotectedprivate。如果标识符以下划线(_)开头,则它对其库是私有的。有关详细信息,请参阅库和导入

  • 标识符可以以字母或下划线(_)开头,后跟这些字符和数字的任意组合。

  • Dart有表达式(有运行时值)和语句(没有)。例如,条件表达式 condition ? expr1 : expr2的值为expr1expr2。将其与没有值的if-else语句进行比较。语句通常包含一个或多个表达式,但表达式不能直接包含语句。

  • Dart工具可以报告两种问题:警告错误。警告只是代码可能无法工作的迹象,但它们不会阻止程序执行。错误可以是编译时或运行时。编译时错误会阻止代码执行;运行时错误会导致代码执行时引发异常

3. Dart 库

文档地址

1. 核心库
2.其他库

除核心库外,Dart 还通过一整套软件包提供了许多 API。 Dart 团队发布了许多有用的补充包,例如:

此外,第三方发布者和更广泛的社区也发布了上千个软件包,支持诸如此类功能:

可以访问 核心库文档,查看关于 Dart 核心库的一系列示例。如果你想要查找其他 API,请参见 常用的 package 页面

二. 编写第一个Flutter应用

三. 学习基础知识

1. dart入门

2. 小部件

“一切都是小部件”===“万事万物都是对象”

小部件库https://api.flutter-io.cn/flutter/widgets/

1.无状态小部件StatelessWidget

如padding、Text、Icon等,基本不会变化

2.有状态小部件StatefulWidget

如计数器、输入框等

3. 一些重要的小部件

3. 布局

1. 对齐行和列中的小部件

mainAxisAlignmentcrossAxisAlignment属性控制行或列对齐其子行的方式。对于行,主轴水平运行,交叉轴垂直运行。对于列,主轴垂直运行,交叉轴水平运行。

[MainAxisAlignmentCrossAxisAlignment枚举提供了用于控制对齐的各种常量。

Flutter包括其他可用于对齐的小部件,特别是Align小部件。

Widget build(BuildContext context) {
  return Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: [
      BorderedImage(),
      BorderedImage(),
      BorderedImage(),
    ],
  );
}
2. 在行和列中调整小部件的大小

可以使用Expanded小部件调整小部件的大小以适合行或列。要修复前面的示例中图像行对其渲染框来说太宽的问题,请使用Expanded小部件包装每个图像。

Widget build(BuildContext context) {
  return const Row(
    children: [
      Expanded(
        child: BorderedImage(width: 150, height: 150),
      ),
      Expanded(
        child: BorderedImage(width: 150, height: 150),
      ),
      Expanded(
        child: BorderedImage(width: 150, height: 150),
      ),
    ],
  );
}

此外,Expanded小部件还可以指定小部件相对于它的兄弟姐妹应该占用多少空间。例如,您可能希望小部件占用两倍于兄弟姐妹的空间。为此,请使用Expanded小部件的flex属性,这是一个确定小部件的flex因子的整数。默认flex因子为1。以下代码将中间图像的flex因子设置为2:

Widget build(BuildContext context) {
  return const Row(
    children: [
      Expanded(
        child: BorderedImage(width: 150, height: 150),
      ),
      Expanded(
        flex: 2,
        child: BorderedImage(width: 150, height: 150),
      ),
      Expanded(
        child: BorderedImage(width: 150, height: 150),
      ),
    ],
  );
}

3. DevTools和调试布局

在某些情况下,框的约束是无界的或无限的。这意味着最大宽度或最大高度设置为double.infinity。当给定无界约束时,试图尽可能大的框将无法正常工作,并且在调试模式下会引发异常。

渲染框以无界约束结束的最常见情况是在弹性框内(RowColumn)和可滚动区域内(例如ListView和其他ScrollView子类)。ListView,例如,尝试扩展以适应其交叉方向上的可用空间(也许它是一个vertically-scrolling块,并尝试与其父块一样宽)。如果您将垂直滚动的ListView嵌套在水平滚动的ListView中,内部列表会尝试尽可能宽,这是无限宽的,因为外部列表可以在该方向上滚动。

构建Flutter应用程序时最常见的错误可能是由于错误地使用布局小部件,称为“无界约束”错误。

4. 列表视图

https://docs.flutter.cn/get-started/fundamentals/layout

ListView是一个类似列的小部件,当它的内容比它的渲染框长时,它会自动提供滚动。使用ListView最基本的方式非常类似于使用ColumnRow

多条动态、多条对话等未知数量的数据展示,用listview

final List<ToDo> items = Repository.fetchTodos();

Widget build(BuildContext context) {
  return ListView.builder(
    itemCount: items.length,
    itemBuilder: (context, idx) {
      var item = items[idx];
      return Padding(
        padding: const EdgeInsets.all(8.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text(item.description),
            Text(item.isComplete),
          ],
        ),
      );
    },
  );
}
5.API参考

以下资源解释了各个API。

4. 状态管理

  • StatefulWidget
  • InheritedWidget使用构造函数、 s 和回调在小部件之间共享状态
  • Listenable当发生更改时使用s 来通知其他小部件
  • 使用模型-视图-视图模型 (MVVM) 作为应用程序架构
1. StatefulWidget

管理状态的最简单方法是使用StatefulWidget,它将状态存储在其自身中

class MyCounter extends StatefulWidget {
  const MyCounter({super.key});

  @override
  State<MyCounter> createState() => _MyCounterState();
}

class _MyCounterState extends State<MyCounter> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Count: $count'),
        TextButton(
          onPressed: () {
            setState(() {
              count++;
            });
          },
          child: Text('Increment'),
        )
      ],
    );
  }
}
2.在小组件中共享状态

应用需要存储状态的一些场景包括:

  • 更新共享状态并通知应用程序的其他部分
  • 监听共享状态变化并在变化时重建 UI

在应用中的不同小部件之间有效地共享状态。最常见的模式是:

  • 使用小部件构造函数 (在其他框架中有时称为“prop drill”)
  • 使用InheritedWidget(或类似的 API,例如提供程序包)。
  • 使用回调通知父窗口小部件某些内容已发生更改
3. InheritedWidget

提供了一种在父窗口小部件中有效托管数据的方法,以便子窗口小部件可以访问它们而无需将它们存储为字段。

要使用InheritedWidget,请扩展该类并 使用InheritedWidget实现静态方法。在构建方法中调用的窗口小部件会创建一个由 Flutter 框架管理的依赖项,以便当此窗口小部件使用新数据重建并返回 true 时,依赖于此的任何窗口小部件都会重建。

class MyState extends InheritedWidget {
  const MyState({
    super.key,
    required this.data,
    required super.child,
  });

  final String data;

  static MyState of(BuildContext context) {
    // This method looks for the nearest `MyState` widget ancestor.
    final result = context.dependOnInheritedWidgetOfExactType<MyState>();

    assert(result != null, 'No MyState found in context');

    return result!;
  }

  @override
  // This method should return true if the old widget's data is different
  // from this widget's data. If true, any widgets that depend on this widget
  // by calling `of()` will be re-built.
  bool updateShouldNotify(MyState oldWidget) => data != oldWidget.data;
}

5. 处理用户输入

1. button
  • ElevatedButton:有一定深度的按钮。使用升降按钮为其他大部分平面布局添加维度。
  • FilledButton:一个填充按钮,应该用于完成流程的重要最终操作,如保存立即加入确认
  • Tonal ButtonFilledButtonOutlinedButton之间的中景按钮。它们在低优先级按钮需要比大纲更强调的上下文中很有用,如Next
  • OutlinedButton:带有文本和可见边框的按钮。这些按钮包含重要的操作,但不是应用程序中的主要操作。
  • TextButton:可点击的文本,没有边框。由于文本按钮没有可见的边框,它们必须依赖它们相对于其他内容的位置来获取上下文。
  • IconButton:带有图标的按钮。
  • FloatingActionButton:悬停在内容上以促进主要操作的图标按钮。

button通常有三个参数,样式、回调及其子按钮,如以下ElevatedButton示例代码所示:

int count = 0;

@override
Widget build(BuildContext context) {
  return ElevatedButton(
    style: ElevatedButton.styleFrom(
      textStyle: const TextStyle(fontSize: 20),
    ),
    onPressed: () {
      setState(() {
        count += 1;
      });
    },
    child: const Text('Enabled'),
  );
}
2. Text

https://docs.flutter.cn/get-started/fundamentals/user-input#text

  1. SelectableText

  2. RichText

  3. TextField

3. Form

https://docs.flutter.cn/get-started/fundamentals/user-input#form

4.chip

Chip是表示特定上下文的属性、文本、实体或操作的紧凑方式。专门的Chip小部件适用于特定用例:

  • InputChip以紧凑的形式表示复杂的信息,例如实体(人、地点或事物)或会话文本。
  • ChoiceChip允许从一组选项中进行单个选择。选择芯片包含相关的描述性文本或类别。
  • FilterChip使用标签或描述性词语来过滤内容。
  • ActionChip表示与主要内容相关的操作。

用户名+头像这类数据可以用该组件

瀑布流或许可以参考该组件

5.DropdownMenu

可选和可筛选的下拉框

一个DropdownMenu允许用户从选项菜单中选择一个选项,并将所选文本放入TextField。它还允许用户根据文本输入过滤菜单项。

配置参数包括以下内容:

  • dropdownMenuEntries提供描述每个菜单项的DropdownMenuEntry列表。菜单可能包含文本标签、前导或尾随图标等信息。(这也是唯一必需的参数。)
  • TextEditingController允许以编程方式控制TextField
  • 当用户选择一个选项时,onSelected回调就会触发。
  • initialSelection允许您配置默认值。
  • 其他参数也可用于自定义小部件的外观和行为。

四. VSCode常用快捷键

在windows中 ⌘ == Ctrl

  • 快速创建widget:在dart文件中输入stfstl出现提示后按⏎即可
  • 快速修复:⌘ + .
  • 自动生成构造函数:选中final参数,快捷键:⌘ + .
  • 添加父组件、变为子组件、删除子组件:⌘ + .
  • 重新打开关闭的编辑页面:⌘+ ⇧ + T
  • 通过匹配文本打开文件:⌘ + T
  • 代码格式化:⇧ + ⌥ + F
  • 打开console: ⌘ + J
  • 查看源码:将光标放到要查看源码的类名或方法名上,长按 ⌥然后的点击查看类的子类:选中要查看的类,然后:⌘+ F12
  • 后退:当跟踪代码的时候,经常跳转到其他类,后退快捷键: ⌃ 导入类的快捷键:将光标放在要导入类的上面,然后按 ⌘+ .全局搜索:⌘+ ⇧+ F
  • 把当前行代码和上一行/下一行代码互换位置: ⌥+ ↑/ ↓
  • 快速复制当前行: ⌥+ ⇧+ ↓
  • 运行项目 flutter run iOS/android -d '指定设备码xxx',运行成功之后 q退出 / r热重载

详细版

参考来源(知乎专栏):https://zhuanlan.zhihu.com/p/699401258

1. Quick Fix (快速修复)

  • MacOS: CMD + .
  • Windows: CTRL + .

2. 显示命令面板

  • MacOS: CMD + Shift + P
  • Windows: CTRL + Shift + P

3. 按文件名进行查找

  • MacOS: CMD + P
  • Windows: CTRL + P

4. 添加 Dart 的依赖

只需打开命令面板 ,然后输入 Dart: Add Dependency 或者 Dart: Add Dev Dependency

就会自动帮你到 pub.dev 上搜索相关依赖包,当你选择后,就会直接添加到项目的 pubspec.yaml 文件并自动安装好

5. Flutter 与 Dart 的代码片段

Flutter 与 Dart 插件里包含了许多代码片段,你可以使用以下快捷键方便快速的将它们添加到你的项目里,如以下几个例子:

  • stless: 插入一个 StatelessWidget
  • stful: 插入一个 StatefulWidget
  • stanim: 插入一个 StatefulWidget 同时带有 AnimationController

6. 查看所有快捷键

  • MacOS: CMD+K CMD+S
  • Windows: CTRL+K CTRL+S

五. 适合 Flutter 开发的 VSCode 扩展

VSCode 的强大之一就是其丰富的扩展,适合的扩展将是你强而有力的帮手,可以让你事半功倍。以下就推荐一些我比较喜爱的扩展:

1. Dart Data Class Generator

当创建不同数据模型的类时,你通常会用到如 copyWith(), toString(), toJson(), fromJson(), toMap(), fromMap(), ==, hashCode 等方法,但如果全部要自己去写,实在是很浪费时间。

现在只需要通过 Dart Data Class Generator 这个扩展,就可以轻松帮你完成!

特别是如果你的数据模型里有很多属性的情况下,这个扩展就是非常方便的!

当然,这类型扩展并不只一个,另一个类似功能的扩展名叫 Json to Dart Model, 其功能也非常强大,可以生成功能完善的数据模型类,出来的效果就像 FreezedJson Serializable

2. Flutter Riverpod Snippets

如果你在使用 Riverpod,就强烈建议你尝试使用这个扩展以快速地帮你完成所需的代码。

使用 Flutter Riverpod Snippets 能让你的代码工作变得更加轻松容易:

3. Error Lens

你想知道你当前的输入是否有错误吗?

Error Lens 这款扩展可以实时高亮显示你当前代码的错误、警告和其他的语法错误,让你马上可以修复相关问题,提升效率

4. Better Comments

Better Comments 是一款可以改善注释的扩展,能在注释中高亮显示警告、注意和待办事项

5. Remove comments

Remove comments 可以直接移除当前文件中所有注释,这对于在创建一个新项目时,需要移除一些系统默认生成的注释时是非常有用的

6. Advanced New File

正常情况下要新建一个文件,要选择左边栏文件夹,然后点 “New File”, 这种方式下你必须要使用鼠标进行点击,而如果在一个大型项目中,要找到对应的文件夹也不是一件容易的事。

Advanced New File 扩展可以让你在任何地方都难轻松建立新的文件,而你只需使用键盘即可完成这一操作

正文到此结束
本文目录