🔑 0
这是我的一个新系列——Flutter学习。学习这个框架,主要是因为我一直想要做一个Python后端和移动前端互相配合的一个应用,而Python没有移动前端框架,并且我也并不太会手机或者是个人电脑的应用开发。因此,为了实现我的这个“目标”,我尝试了这个新生的框架。
📘 目录
- ✅ 我为何选择Flutter
- ❓ 所以,啥是Flutter,Flutter的开发环境如何部署
- 🧩 理解
Widget
、Widget树 - 💠 理解
StatelessWidget
和StatefulWidget
- 📱 理解
MaterialApp
和Scaffold
- ⛵ 实战:Hello, world
- ⚡ Hot Reload与Hot Restart
✅ 1
我为何选择了Flutter
首先,我是一个人在“单打独斗”。也就是说,我没什么团队,但在我的设想下,我的App是可以跨平台适配的。由于其他原因,我并没有足够的时间完全投身于应用的开发中。所以,我需要一个跨平台框架。
另外,我喜欢声明式编写UI的方式。
并且,Flutter高保真、有性能。
❓ 2
所以,啥是Flutter?
Flutter介绍:
腾讯技术工程的文章 - 知乎
安装和环境配置:
安装和环境配置 - Flutter 中文文档 - Flutter 中文资源
Flutter使用Dart作为编程语言!如果想要入门Flutter,写好一手Dart非常重要。Dart的风格类似于JavaScript,又像其他的一些语言。Dart官方语言概览:
Dart编程语言概览 - Dart中文文档 - Dart中国
🧩 3
理解Widget
、Widget树
在Flutter中,Widget
构成应用程序!从一个按钮,一个图标,再到一段文字,甚至到应用本身,都是Widget
。你可以将Widget
看作是Web开发中的“组件”。
Flutter 的 Widget
渲染采用的是类似 React 的框架:当Widget
的状态出现变化,需要刷新界面时,框架会先计算从上一个状态转换到下一个状态所需的最小更改,再去刷新界面。
我们可以看到,在Widgets层的下面,有:
- Rendering(渲染层)
- Animation\Painting\Gestures (动画、绘图、手势)
- Foundation (基础库层)
这些实现了基本层面的东西,是Flutter大厦的基础。不过,我们用到的会比较少,因为如此开发会导致程序的冗长和复杂——毕竟,如果没有必要,我们不能在造轮子的工程里面自我感动。也就说,我们一般来说用的最多的,就是封装好的Widget
。
当然,如果你注意到了,那么,你会发现上面还有一层:
Material和Cupertino
Flutter已经帮我们封装好了Material(Android)风格和Cupertino(iOS)风格的Widget
!我们可以直接使用已经封装好的Material和Cupertino Widget。这样一来,能够大大提升开发效率,并且可以写出最接近于Native UI的用户界面,快速实现美观易用的应用程序。
理解组件树
在Flutter中,Widget
的组合方式是Widget树。
下面这个动图很好地说明了Flutter的Widget树中“包含与被包含”的关系:
Flutter的Widget树 - (动图是我自己做的,转载请注明出处)
在Widget树中,如果一个Widget A包含在Widget B内,则称B是A的父Widget,A是B的子Widget。例如在刚才的组件树中,MaterialApp是Scaffold的父Widget,Scaffold是MaterialApp的子Widget。
我们还要认识一个概念——根Widget(Root Widget)。根Widget就相当于Widget树的“宗师”,在刚才的组件树中,根Widget就是MaterialApp。Flutter会默认将根Widget充满屏幕。但是你必须注意到的一点是,如同在HTML中,最外面的HTML标签必须得是,在Flutter中,根Widget必须得是以下三个之中的其中一个:
MaterialApp
这是一个实现了Material Design组件的根Widget,它的子Widget都是Material风格。
我们最常用到这个根Widget,因为毕竟Material Design是Google亲儿子,它的支持最为健全,也最易于进行开发。CupertinoApp
这是一个实现了Cupertino(iOS)风格的根Widget,它的子Widget都是Cupertino风格。WidgetsApp
这是一个你可以自定义风格的根Widget。其中海阔天空任你发挥。
💠 4
理解StatelessWidget
和StatefulWidget
StatelessWidget
就是没有状态的Widget
。如果它在程序运行时状态不需要改变,就可以使用这种Widget
。
StatefulWidget
就是有状态的Widget
。它在程序运行时,状态被允许发生改变。
你编写的Widget
均继承于这两个类中的其中一个。
一会儿我们马上就会用到StatelessWidget
。我以后会介绍StatefulWidget
,目前我们暂时还用不着。
📱 5
理解MaterialApp和Scaffold
我们刚才提到过,MaterialApp
是根Widget,这个根Widget表明了这个应用程序的交互界面采用Material Design的Widget
。如果想要使用Material风格的Widget
,根Widget就必须采用MaterialApp。
Scaffold
规定了这个界面的格式,包括了AppBar
,Body
等一系列的布局。这是Material Design界面的基本结构,使用这些布局也必须用Scaffold
。
所以,一个常见的Flutter App的格式就是——它的根Widget是MaterialApp
,而这个成为了“土壤”的根Widget的子Widget就是Scaffold
,我们在Scaffold
内实现界面。
⛵ 6
实战:Hello, world——以及对前文所提及概念的再理解
import 'package:flutter/material.dart';
void main() => runApp(HelloWorld());
class HelloWorld extends StatelessWidget {
@override
Widget build(BuildContext buildContext) {
return MaterialApp(
title: 'Flutter Demo_0',
home: Scaffold(
appBar: AppBar(
title: Text('It \'s JUST a greeter')
),
body: Center(
child: Text('Hello, world!')
)
)
);
}
}
众所周知,学习Flutter的最好方法,就是把Source Code怼到脸上自己理解。
我们看第一句:
import 'package:flutter/material.dart';
这个语句导入了flutter
库中的material.dart
,这个文件中包含了MaterialApp
及一系列Material组件的实现。
接下来:
void main() => runApp(HelloWorld());
main()
是Dart程序的入口。runApp()
可以让你的Flutter App运行起来,这个函数只需要传递一个参数,那就是你的根Widget的实例。
class HelloWorld extends StatelessWidget {
一切由你写出来的Widget
,都必须继承StatelessWidget
与StatefulWidget
中的任意一个。这里继承了StatelessWidget
,意味着在程序运行的过程中,这个Widget
的状态不会发生变化。
然后,我们override
了一个build()
函数,build()
函数返回Widget
的本体。这个函数传入一个参数buildContext
(它是BuildContext
类型),这是应用上下文。
MaterialApp
有以下这几个属性
title
指的是应用进程的名称(不是应用名)home
这个参数必须传入一个Scaffold
,在Scaffold
内实现界面- 其它
color
应用图标背景颜色theme
传入一个themeData
对象,是应用的主题数据- …
Scaffold
有以下几个属性
appBar
传入一个AppBar
backgroundColor
应用程序的背景颜色body
应用程序主要要显示的内容- …
AppBar
的title
属性我这里传入的是一个Text
,表示界面顶栏要显示的标题。
Center
表示其中的Widget
在x, y轴上均居中显示。如果只有一个子Widget则将这个子Widget传入它的child
属性,如有多个就将一个<Widget>[]
传入children
属性。
Text
是文本。
最终,我们实现了一个这样的界面:
⚡ 7
Hot Reload和Hot Restart
调试时,⚡图标代表Hot Reload。这可以在不重新编译应用包的情况下把代码上的变化立马在调试用的虚拟机(或实体机)中呈现出来。
但是,在出现以下情况时,Hot Reload没有用:
- 枚举类型更改为常规的类或者常规的类变为枚举类型
- main() 方法里的更改
- 全局变量(global variables)和静态字段(static fields)的更改
- 代码更改会影响 APP 状态的不能使用 Hot Reload
- 代码出现编译错误的不能使用 Hot Reload
在这种情况下,你可以使用 Hot Restart来实现快速重启。
这两种Flutter特性均是加快开发速度的利器。
🏁 -1
结语
目前,我们就算是一起走入了Flutter的殿堂。在这之后,我们会一起学习Flutter的各个组件,实现一个Flutter App,并最终实现我的“目标”。