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是强类型的,但类型注释是可选的,因为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没有关键字
public
、protected
和private
。如果标识符以下划线(_
)开头,则它对其库是私有的。有关详细信息,请参阅库和导入。标识符可以以字母或下划线(
_
)开头,后跟这些字符和数字的任意组合。Dart有表达式(有运行时值)和语句(没有)。例如,条件表达式
condition ? expr1 : expr2
的值为expr1
或expr2
。将其与没有值的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. 对齐行和列中的小部件
mainAxisAlignment
和crossAxisAlignment
属性控制行或列对齐其子行的方式。对于行,主轴水平运行,交叉轴垂直运行。对于列,主轴垂直运行,交叉轴水平运行。
[
MainAxisAlignment
和CrossAxisAlignment
枚举提供了用于控制对齐的各种常量。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
。当给定无界约束时,试图尽可能大的框将无法正常工作,并且在调试模式下会引发异常。
渲染框以无界约束结束的最常见情况是在弹性框内(Row
或Column
)和可滚动区域内(例如ListView
和其他ScrollView
子类)。ListView
,例如,尝试扩展以适应其交叉方向上的可用空间(也许它是一个vertically-scrolling块,并尝试与其父块一样宽)。如果您将垂直滚动的ListView
嵌套在水平滚动的ListView
中,内部列表会尝试尽可能宽,这是无限宽的,因为外部列表可以在该方向上滚动。
构建Flutter应用程序时最常见的错误可能是由于错误地使用布局小部件,称为“无界约束”错误。
4. 列表视图
https://docs.flutter.cn/get-started/fundamentals/layout
ListView
是一个类似列的小部件,当它的内容比它的渲染框长时,它会自动提供滚动。使用ListView
最基本的方式非常类似于使用Column
或Row
。
多条动态、多条对话等未知数量的数据展示,用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 Button
:FilledButton
和OutlinedButton
之间的中景按钮。它们在低优先级按钮需要比大纲更强调的上下文中很有用,如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
SelectableText
RichText
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
文件中输入stf
或stl
出现提示后按⏎即可 - 快速修复:⌘ + .
- 自动生成构造函数:选中
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, 其功能也非常强大,可以生成功能完善的数据模型类,出来的效果就像 Freezed 和 Json 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 扩展可以让你在任何地方都难轻松建立新的文件,而你只需使用键盘即可完成这一操作
- 本文标签: flutter
- 本文链接: https://www.tianyajuanke.top/article/90
- 版权声明: 本文由吴沛芙原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权