持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情
2.【Flutter从0到1】番茄计时APP:原型图+功能梳理
4.【Flutter从0到1】番茄计时APP:跑通第一个页面
5.【Flutter从0到1】番茄计时APP:Dart 语言速览基础篇
6.【Flutter从0到1】番茄计时APP:Dart 语言速览进阶篇
刚开始写小程序的时候,翻了翻文档,就开搞了。本来以为Flutter上手很快,大意了,要了解的东西还不少。
Flutter为拥有其他平台开发经验的开发者提供了对比文章,我看了写给Android和web开发者的指南,总算心里有底了。
又用了几个小时时间,看了一遍文档,和Dart一样,我将我认为的重点知识整理成两篇文章,分为基础篇和进阶篇,本篇为基础篇。
Flutter是一个UI框架,和上手其他UI框架一样,重点关注以下几点:
布局、组件、路由、数据交互、数据存储/缓存、测试、打包、持续部署。
Widgets
基础内容
widget中文翻译是小部件,在Flutter中,任何东西都是widget,一个按钮一张图一段文字, widget类似Android中的View,具体也是有差异的。
组件分为有状态组件和无状态组件:
- 无状态组件(StatelessWidget) 无状态组件,可以理解为将外部传入的数据转化为界面展示的内容,只会渲染一次。 StatelessWidget继承自Widget类,重写了createElement()方法。
class GreenFrog extends StatelessWidget {
const GreenFrog({ Key? key }) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(color: const Color(0xFF2DBD3A));
}
}
复制代码
- 有状态组件(StatefulWidget) 有状态组件,是定义交互逻辑和业务数据,可以理解为具有动态可交互的内容界面,会根据数据的变化进行多次渲染。 和StatelessWidget一样,StatefulWidget也是继承自Widget类,并重写了createElement()方法,不同的是返回的Element 对象并不相同;另外StatefulWidget类中添加了一个新的接口createState()。
class YellowBird extends StatefulWidget {
const YellowBird({ Key? key }) : super(key: key);
@override
State<YellowBird> createState() => _YellowBirdState();
}
class _YellowBirdState extends State<YellowBird> {
@override
Widget build(BuildContext context) {
return Container(color: const Color(0xFFFFE306));
}
}
复制代码
下面是基础的widget:
- Text:Text widget 可以用来在应用内创建带样式的文本。
- Row, Column:类似于Android中的
LinearLayout
,这两个 flex widgets 可以让你在水平 (Row) 和垂直(Column) 方向创建灵活的布局。它是基于 web 的 flexbox 布局模型设计的。 - Stack:Stack widget 不是线性(水平或垂直)定位的,而是按照绘制顺序将 widget 堆叠在一起。你可以用 Positioned widget 作为Stack 的子 widget,以相对于 Stack 的上,右,下,左来定位它们。 Stack 是基于 Web 中的绝对位置布局模型设计的。
- Container:就像web中万能的
div
一样,Container widget 可以用来创建一个可见的矩形元素。 Container 可以使用 BoxDecoration 来进行装饰,如背景,边框,或阴影等。 Container 还可以设置外边距、内边距和尺寸的约束条件等。另外,Container可以使用矩阵在三维空间进行转换。
生命周期
Flutter中的生命周期是指有状态组件的生命周期。
- createState: 当创建一个有状态的widget时,框架会调用一个createState()方法,而且必须重载该方法。
- initState: 当这个对象被插入到树中时调用这个方法。每个 State 对象将只调用一次。在这里,我们可以初始化小部件所需的变量,例如AnimationController。
- didChangeDependencies: 在initState之后以及 State 对象的依赖关系通过InheritedWidget发生变化时立即调用此方法。
- build: 每次重新构建小部件时都会调用此方法。这可以在调用initState、didChangeDependencies、didUpdateWidget或通过调用setState 更改状态时发生。
- didUpdateWidget: 每当小部件配置更改时调用此方法。一个典型的情况是父级通过构造函数将一些变量传递给子级小部件。
- deactivate: 从树中删除对象时调用此方法。
- dispose: 当该对象从树中永久删除时调用此方法。在这里,我们应该释放该对象保留的所有资源,例如停止动画。调用此方法的一个示例是使用 Navigator 的pushReplacement() 将当前小部件替换为新小部件。
关于布局的详细内容,建议通读官方文档:flutter.cn/docs/develo…
路由
Flutter有命令式路由机制(Navigator组件)和声明式路由机制(Router组件)。对于小型应用程序来说,通常只需通过 MaterialApp 构造函数中的 MaterialApp.routes 属性,加以使用 Navigator API,就可以很好地提供服务。
Navigator案例:flutter.cn/docs/cookbo…
关于flutter router详细解析,建议看这篇文章:medium.com/flutter/lea…
数据交互
状态管理
Flutter应用是声明式的,也就是说当应用状态发生改变时,会触发用户界面的重绘,无需像原生Android中去主动改变用户界面本身。类似于Vue中的双向数据绑定。
网络请求
http软件包提供了网络请求的功能,基础功能都已封装完成。支持Android,iOS,Web,桌面端等。
使用示例:
import 'package:http/http.dart' as http;
var url = Uri.parse('https://example.com/whatsit/create');
var response = await http.post(url, body: {'name': 'doodle', 'color': 'blue'});
print('Response status: ${response.statusCode}');
print('Response body: ${response.body}');
print(await http.read(Uri.parse('https://example.com/foobar.txt')));
复制代码
JSON
相关文档地址:flutter.cn/docs/develo…
数据存储/缓存
对于简单的数据存储,比如存储一些键值对,推荐使用shared_preferences包。
如果需要存储或查询大量数据,可以使用sqflite包。
- shared_preferences:为简单数据包装特定于平台的持久存储(iOS 和 macOS 上的 NSUserDefaults,Android 上的 SharedPreferences 等)。数据可能会异步持久化到磁盘,并且不能保证写入返回后会持久化到磁盘,所以这个插件一定不能用于存储关键数据。
- sqflite:Flutter 的 SQLite 插件。支持 iOS、Android 和 MacOS。