学习资料是:《Flutter实战》电子书
https://book.flutterchina.club/
一、第一章:搭建环境
- 安装Flutter SDK
- 安装Android Studio
- 配置Android AVD (踩坑踩的我想睡觉,一开始是显示AVD been killed,一会儿又是无法验证)
- 安装Flutter和Dart插件
二、创建应用程序
- 选择 File>New Flutter Project 。
- 选择 Flutter application 作为 project 类型, 然后点击 Next
- 输入项目名称 hi_flutter,然后点击 Next
- 点击 Finish
- 等待Android Studio安装SDK并创建项目
- RUN
命途多舛,冯唐易老、李广难封
看起来像是网络问题、进设置配置代理,再试,确实是跑起来了,不过…
又卡在了Activating Dart DevTools这儿了
经过漫长的折腾,正式进入学习了
三、第一个Flutter应用程序
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
几乎看不懂是啥意思
布局勉强 理解一点点
- 导入包
import 'package:flutter/material.dart';
导入了Material UI组件库。Material 是一种标准的移动端和web端的视觉设计语言, Flutter默认提供了一套丰富的Material风格的UI组件。
2. 应用入口
void main() => runApp(MyApp());
main
函数使用了(=>
)符号,这是Dart中单行函数或方法的简写。- Flutter 应用中
main
函数为应用程序的入口 MyApp
类代表Flutter应用,它继承了StatelessWidget
类,这也就意味着应用本身也是一个widgetrunApp
它接受一个Widget
参数
3.首页
MyHomePage
是Flutter应用的首页,它继承自StatefulWidget
类,表示它是一个有状态的组件(Stateful widget)。- Stateful widget可以拥有状态,这些状态在widget生命周期中是可以变的,而Stateless widget是不可变的
- State类:该组件的状态
设置状态的自增函数
大概明白就是,页面是一个Widget,还有状态,状态可以通过createState() 去修改,创建状态后build,则构建页面布局
Scaffold
是 Material 库中提供的页面脚手架,它提供了默认的导航栏、标题和包含主屏幕widget树(后同“组件树”或“部件树”)的body
属性,组件树可以很复杂。本书后面示例中,路由默认都是通过Scaffold
创建body
的组件树中包含了一个Center
组件,Center
可以将其子组件树对齐到屏幕中心。此例中,Center
子组件是一个Column
组件,Column
的作用是将其所有子组件沿屏幕垂直方向依次排列; 此例中Column
子组件是两个Text
,第一个Text
显示固定文本 “You have pushed the button this many times:”,第二个Text
显示_counter
状态的数值floatingActionButton
是页面右下角的带“+”的悬浮按钮,它的onPressed
属性接受一个回调函数,代表它被点击后的处理器,本例中直接将_incrementCounter
方法作为其处理函数
4. 一个简单路由
- StatelessWidget
- TextButton 按钮
- Navigator 操作路由到新增的Widget
MaterialPageRoute
继承自PageRoute
类,PageRoute
类是一个抽象类,
表示占有整个屏幕空间的一个模态路由页面,它还定义了路由构建及切换时过渡动画的相关接口及属性。
MaterialPageRoute
是Material组件库提供的组件,它可以针对不同平台,实现与平台页面切换动画风格一致的路由切换动画:
二、路由注册
MaterialApp(
title: 'Flutter Demo',
initialRoute:"/", //名为"/"的路由作为应用的home(首页)
theme: ThemeData(
primarySwatch: Colors.blue,
),
//注册路由表
routes:{
"new_page":(context) => NewRoute(),
"/":(context) => MyHomePage(title: 'Flutter Demo Home Page'), //注册首页路由
}
);
简单注册一下路由,接下来是使用路由
onPressed: () {
Navigator.pushNamed(context, "new_page");
//Navigator.push(context,
// MaterialPageRoute(builder: (context) {
// return NewRoute();
//}));
},
直接使用 Navigator
的 pushNamed
方法即可打开新的路由
路由参数传递
routes:{
"new_page":(context) => EchoRoute(),
} ,
在路由页面通过RouteSetting对象获取路由参数
class EchoRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 获取路由参数
var args = ModalRoute.of(context).settings.arguments;
}
}
打开路由时传递参数
Navigator.of(context).pushNamed("new_page", arguments: "hi");
路由生成钩子
可以用来做一些判断用户是否有权限访问页面的操作
// 设置路由拦截
onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute(builder: (context) {
String routeName = settings.name;
}
);
},
三、包管理
Flutter使用配置文件 pubspec.yaml
(位于项目根目录)来管理第三方依赖。
下面,我们逐一解释一下各个字段的意义:
name
:应用或包名称。description
: 应用或包的描述、简介。version
:应用或包的版本号。dependencies
:应用或包依赖的其它包或插件。dev_dependencies
:开发环境依赖的工具包(而不是flutter应用本身依赖的包)。flutter
:flutter相关的配置选项。
Pub仓库
Pub仓库地址:(https://pub.dev/) 是Google官方的Dart Packages仓库,类似与node中的npm仓库
这一章还算简单
四、资源管理
从我前端开发的经验来看,应该是静态资源的管理,比如配置文件,图标,图片等等
指定 assets
和包管理一样,Flutter也使用pubspec.yaml
(opens new window)文件来管理应用程序所需的资源,举个例子
assets
指定应包含在应用程序中的文件,
每个asset都通过相对于pubspec.yaml
文件所在的文件系统路径来标识自身的路径。
asset的声明顺序是无关紧要的,asset的实际目录可以是任意文件夹(在本示例中是assets文件夹)。
Asset 变体(variant)
那么这两个graphics/background.png
和graphics/dark/background.png
都将包含在您的asset bundle中。前者被认为是_main asset_ (主资源),后者被认为是一种变体(variant)。
在做多皮肤的时候还是挺有用的。
加载文本assets(如JSON文件)
- 通过
rootBundle
(opens new window)对象加载:每个Flutter应用程序都有一个rootBundle
(opens new window)对象, 通过它可以轻松访问主资源包,直接使用package:flutter/services.dart
中全局静态的rootBundle
对象来加载asset即可。
加载图片
要加载图片,可以使用 AssetImage
(opens new window)类。例如,我们可以从上面的asset声明中加载背景图片:
注意,AssetImage
并非是一个widget, 它实际上是一个ImageProvider
,有些时候你可能期望直接得到一个显示图片的widget,那么你可以使用Image.asset()
方法,如
Widget build(BuildContext context) {
return Image.asset('graphics/background.png');
}
调试Flutter应用
- Dart分析器 – 静态代码检查工具
flutter analyze
测试代码 - Dart Observatory(语句级的单步调试和分析器) – 默认监听
http://127.0.0.1:8000/
支持分析、检查堆 debugger()
声明 – 编程式断点print
、debugPrint
、flutter logs
- 调试模式断言 –
assert
语句
… 太多了,很多东西我都不理解后面实战以后再来看看
Flutter异常捕获
- Dart单线程模型 – 发生未被捕获的异常时候不会退出
Dart 在单线程中是以消息循环机制来运行的,其中包含两个任务队列
- 一个是“微任务队列” microtask queue
- 另一个叫做“事件队列” event queue
从图中可以发现,微任务队列的执行优先级高于事件队列。
在事件循环中,当某个任务发生异常并没有被捕获时,程序并不会退出,而直接导致的结果是当前任务的后续代码就不会被执行了,也就是说一个任务中的异常是不会影响其它任务执行的
- 异常捕获
try/catch/finally
捕获代码异常(Flutter默认的处理方式是弹一个ErrorWidget)
也有很多无法理解的内容,暂时性跳过后面再来看
暂无评论