Flutter面经
StatelessWidget和StatefulWidget
在Flutter中,widget分为两类:Stateful(有状态)和 stateless(无状态)widget。
stateless widget 没有内部状态,Icon、IconButton, 和Text都是无状态widget, 它们都是 StatelessWidget的子类。
stateful widget 是动态的,用户可以和其交互(例如输入一个表单、 或者移动一个slider滑块),或者可以随时间改变 (也许是数据改变导致的UI更新)。Checkbox, Radio, Slider, InkWell, Form, and TextField 都是 stateful widgets, 它们都是 StatefulWidget的子类。
StatelessWidget
Stateless widgets 是不可变的, 这意味着它们的属性不能改变——所有的值都是最终的。
如果无状态Widget里面有子Widget,并且子Widget是有状态的,则子Widget的内容是可以通过setState来更改的。无状态Widget影响的仅仅是自己是无状态的,不回影响他的父Widget和子Widget。
StatefulWidget
Stateful widgets 持有的状态可能在widget生命周期中发生变化。
创建一个有状态的widget需要进行以下操作:
要创建一个自定义有状态widget,需创建两个类:StatefulWidget和State。
我们要定义一个widget类,继承自StatefulWidget。
子State,包含该widget状态并定义该widget build()方法的类,它继承自State。
状态对象包含widget的状态和build() 方法。
当widget的状态改变时,状态对象调用setState(),告诉框架重绘widget
class TextPage extends StatefulWidget{
@override
TextPageState createState() => new TextPageState();
}
class TextPageState extends State<TextPage>{
@override
Widget build(BuildContext context)
}
Navigator路由
有显示跳转
Navigator.push(context, MaterialPageRoute(builder: (context) => LoginPage()));
还有隐式跳转
这种跳转需要先定义,后使用
Navigator.push 用来执行 Route 的入栈操作,就可以通过指定的 Route 跳转到对应的页面了
Navigator.pop 用来执行 Route 的退栈操作,即页面回退,可以添加可选参数 result 作为页面返回时携带的参数
context跨组件获取数据的一个封装
Flutter 中的生命周期
-
initState()
表示当前 State 将和一个 BuildContext 产生关联,但是此时BuildContext 没有完全装载完成,如果你需要在该方法中获取 BuildContext ,可以 new Future.delayed(const Duration(seconds: 0, (){//context}); 一下。 -
didChangeDependencies()
didChangeDependencies() 在 initState() 之后调用,当 State 对象的依赖关系发生变化时,该方法被调用,初始化时也会调用。 -
deactivate()
deactivate() 当 State 被暂时从视图树中移除时,会调用这个方法,同时页面切换时,也会调用。 -
dispose()
dispose() Widget 销毁了,在调用这个方法之前,总会先调用 deactivate()。
Scaffold
一个完整的页面可能会包含导航栏、抽屉菜单以及底部导航等等。如果每个路由页面都需要开发者自己手动去实现这些组件,这将会是很差的体验。在 Material 组件库中,提供了 Scaffold 组件用于搭建一个页面的骨架,让我们很容易的拼装出一个完整的页面。
- AppBar 设置导航栏标题、导航栏菜单、导航栏底部的 Tab
- TabBar 组件用于快速生成 Tab 菜单。在导航栏的底部通常是一组 Tab 菜单,可以通过上面 AppBar 的 bottom 属性来指定这组菜单
- TabBarView
通过上面的 TabBar 只能生成一个静态的菜单,Tab 菜单和 Tab 页面切换需要同步,然而实现这一功能的就需要通过 TabBarView 组件了。TabBarView 组件不仅可以轻松实现 Tab ,而且可以非常容易配合 TabBar 来实现同步切换和滑动状态同步 - 抽屉菜单 drawer 、endDrawer 两个属性用于表示一个页面的左、右抽屉菜单。
- 底部 Tab 导航栏 提供了 bottomNavigationBar 属性来指定底部导航,Material 组件库提供了 BottomNavigationBar 和 BottomNavigationBarItem 来实现底部导航。
- 详细
Row和Column
Row和Column是flutter中最基础的容器组件,Row用来水平放置子组件,Column用来垂直放置子组件。它们都可以设置子组件的对齐方式。重点需要了解它们有哪些对齐方式,以及如何对齐的。
布局行为
Row默认行为:在水平方向会尽可能大,大到会撑满parent;在垂直方向会尽可能小,小到能包裹住children。children在水平居左,垂直方向上居中。
Column默认行为:在垂直方向上会尽可能大,大到会撑满parent;在水平方向会尽可能小,小到能包裹住children。children在垂直居上,水平方向上居中。
mainAxisAlignment 主轴对齐方式
crossAxisAlignment 纵轴对齐方式
详细
async,await,Future
异步操作让您的程序在等待另一个操作完成的同时完成工作:
例:通过网络获取数据。写入数据库。从文件中读取数据。
-
Future对象表示异步操作的结果,我们通常通过then()来处理返回的结果
-
async用于标明函数是一个异步函数,其返回值类型是Future类型
-
await用来等待耗时操作的返回结果,这个操作会阻塞到后面的代码
-
Future 表示异步操作的结果,可以有两种状态:未完成或已完成。
未完成:
当你调用一个异步函数时,它会返回一个未完成的Future。那个Future正在等待函数的异步操作完成或抛出错误。
完成:
如果异步操作成功,future 以一个值结束。否则,它会以错误完成。
完成返回的值:
type 的 future 以 typeFuture的值结束T。例如,带有类型的未来Future会产生一个字符串值。如果未来不产生可用值,那么未来的类型是 Future.
错误:
如果函数执行的异步操作由于任何原因失败,future 会以错误结束。
关键术语:
同步操作:同步操作阻止其他操作执行,直到它完成。
同步函数:同步函数只执行同步操作。
异步操作:一旦启动,异步操作允许在完成之前执行其他操作。
异步函数:异步函数至少执行一个异步操作,也可以执行同步操作。
详细
Stream 流异步通信 StreamController
Stream 是一个抽象类,用来表示一个序列的异步数据,Stream流分类:
- 单订阅流(Single Subscription),这种流最多只能有一个监听器(listener)
- 多订阅流(Broadcast),这种流可以有多个监听器监听(listener)
Stream可以接受任何类型的数据,Stream 有同步流和异步流之分,它们的区别在于同步流会在执行 add,addError 或 close 方法时会立即发送事件,而异步流总是在事件队列中的代码执行完成后再发送事件。
详细
Animation动画
1、Animation
Animation是一个抽象(abstract)类,它不能直接实例化,比较常用得Animation类是Animation。Animation对象再一段时间内生成一个区间值。Animation得输出可以是线性得,也可以是非线性得,因此Animation本身和UI渲染没有任何关系,它拥有动画当前值和状态。通过给Animation对象添加监听器,可以监听动画得每一帧及动画状态。添加监听得方法有:
addListener():每一帧都会调用,一般会在其中调用setState()来触发UI重建;
addStatusListener():添加动画状态改变监听器,当动画状态开始
结束、正向、反向发生变化时调用。
2、Curve
动画得过程时线性得还是非线性得是由Curve确定得,Curve得作用和android中得Interpolator(插值)时一样得,负责控制动画变化得速率,通俗地讲就是使动画得效果能够以匀速、加速、抛物线等各种速率变化。
使用CurvedAnimation来指定动画曲线,代码如下:
animation = CurvedAnimation(parent: animationController, curve: Curves.bounceIn),
3、AnmationController
AnmationController使动画控制器,控制动画得播放、停止等。AnmationController继承自Animation,是一个特殊得Animation对象,屏幕刷新得每一帧都会生成一个新得值,默认情况下它会线性地生成0.0~1.0的值。
4、Tween
AnimationController继承自Anmation,输出的值只能为double类型。如果要求动画的效果是颜色变化,这时候AnimationController并不能满足需求,而Tween继承自Animatable,它提供了evaluate方法以获取当前映射值。使用Tween对象需要调用animate方法传入控制器对象,并返回一个animation。
5、AnimatedList
AnimatedList:列表中数据发生变化时加入过渡动画。AnimatedList得构建首先需要itemBuilder,itemBuilder是一个函数,列表的每一个索引会调用,这个函数有一个animation参数,可以设置成任何一个动画。如果初始的时候数据不为空,AnimatedList的构建需要initialItemCount,initialItemCount表示数据的数量。当有数据添加或者删除时,调用AnimatedListState的对应的方法:
AnimatedListState.insertItem
AnimatedListState.removeItem
Container
Container(容器控件)在Flutter是经常使用的控件,它就相当于我们HTML里的
各种按钮
- FloatingActionButton 圆形的按钮,一般出现在屏幕内容的前面,用来处理界面中最常用、最基础的用户动作。
- RaisedButton 凸起的按钮,默认带有灰色背景,被点击后灰色背景会加深。
- FlatButton 扁平化的按钮,默认透明背景,被点击后会呈现灰色背景。
- OutlineButton OutlineButton默认有一个边框,不带阴影且背景透明。按下后,边框颜色会变亮、同时出现背景和阴影(较弱)
- IconButton IconButton是一个可点击的Icon,不包括文字,默认没有背景,获取焦点后显示背景。
- 带图标的按钮 RaisedButton、FlatButton、OutlineButton都有一个icon 构造函数,通过它可以创建带图标的按钮。
- InkWell 给其他控件添加水波纹点击效果
const FlatButton({
Key key,
@required VoidCallback onPressed, // 点击回调
VoidCallback onLongPress,//长按回调
ValueChanged<bool> onHighlightChanged,
ButtonTextTheme textTheme,
Color textColor,//按钮文字颜色
Color disabledTextColor,//按钮禁用时的文字颜色
Color color,//按钮背景颜色
Color disabledColor,//按钮禁用时的背景颜色
Color focusColor,//按钮按下时的背景颜色
Color hoverColor,//悬停时的背景颜色
Color highlightColor,//高亮时背景颜色
Color splashColor,//点击时,水波动画中水波的颜色
Brightness colorBrightness,//按钮主题,默认是浅色主题
EdgeInsetsGeometry padding,//按钮的内边距
ShapeBorder shape,//外形
Clip clipBehavior = Clip.none,
FocusNode focusNode,
bool autofocus = false,
MaterialTapTargetSize materialTapTargetSize,
@required Widget child,//按钮的内容
})
其中shape有下面三种:
RoundedRectangleBorder:圆形矩形边框
ContinuousRectangleBorder:连续矩形边框
BeveledRectangleBorder : 斜角矩形边框
RaisedButton(
color: Colors.blue, // 按钮背景色
highlightColor: Colors.blue[700],// 按钮高亮后的背景色
colorBrightness: Brightness.dark,// 使用深色主题,保证按钮文字颜色为浅色
splashColor: Colors.grey,// 点击时,水波动画中水波的颜色
child: Text("Submit"),// 文本
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0)), //圆角矩形
onPressed: () {},
)
FlatButton(
color: Colors.yellow, //设置背景色为黄色
shape: ContinuousRectangleBorder(
borderRadius: BorderRadius.circular(20.0)), //设置斜角矩形边框
colorBrightness: Brightness.light, //使用亮色主题,保证按钮文字颜色为深色
onPressed: () {},
child: Icon(Icons.add)
)
showDialog弹框
Dio网络通信
dio是一款Flutter 网络请求框架,一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时、自定义适配器等
Dart语言
- Dart是单线程的语言,所以如果线程中顺序执行的时候如果遇到一些耗时阻塞的操作,比如数据请求,延时操作等,就会产生卡顿,所以用异步来解决。
- 级联运算符 (…) 可以让你在同一个对象上连续调用多个对象的变量或方法。
我项目中所用
//强制横屏
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight
]);
//隐藏顶部状态栏
SystemChrome.setEnabledSystemUIOverlays([]);
//屏幕宽高
MediaQuery.of(context).size.width
MediaQuery.of(context).size.height
- SizedBox 用来设置两个控件之间的间距
- AppBar 设置导航栏标题、导航栏菜单、导航栏底部的 Tab
- Text
- RaisedButton (onPressed属性)(child 子组件)
- Column和Row
- Center 将子控件放在其内部中心,里面只能放一个child,但是child里面可以放Container
- Container 容器
- BoxDecoration 容器decoration属性中可以添加这个容器的装饰
- BoxFit.fill 布满整个父容器
- DecorationImage 容器的背景
- InputDecoration 输入框的装饰
- OutlineInputBorder 输入框的外边框
- borderRadius 圆角
- AssetImage 引用图片
- Stack 层叠布局
- Positioned 定位
- Text 文本
- TextStyle 文本样式
- TextField 文本输入框
- CustomPaint
- Opacity 透明度
- FlatButton 按钮
- setState 整个页面的刷新
- TextField 文字输入框
- onChanged 输入内容变化时,调用函数进行改变
- onPressed 按钮按下时,调用函数改变
- onConfirm 确定事件
- Color.fromARGB(255, 100, 219, 229) 颜色
- Icon 图片
- showDialog 对话框
- AlertDialog 弹框
- PageView 轮播的组件
- PageController 轮播控制器
- nextPage 轮播下一张图
- AudioCache和AudioPlayer 音频播放控制
- Duration 持续时间
- Timer 时间控制器
- GridView 表格组件
- StatefulWidget 有状态的Widget树,可以更新视图
- StatelessWidget 无状态的Widget树
- StreamController 流控制器
- StreamBuilder 流将要更新的组件,写在这个下面,需要绑定流控制器
- cancel 时间控制器的销毁
- close 流控制器的关闭销毁
- stop音频控制器的停止
- Curves 动画的过渡方式
- ClipRRect 裁剪布局 将 child 剪裁为圆角矩形
- GestureDetector 手势控制
- onTapDown 手指按下
- onTap 手指抬起
- onTapCancel 手指按下后滑动移出
- PieChatWidget echarts中的饼图
- Switch 开关
- showDatePicker 日期控件
- DateTime 日期
- SingleChildScrollView 滚动组件
- ListView 列表控件,可上下滑动
- Padding 可以设置边距问题
- EdgeInsets.only(left: 20,bottom: 20,top: 20,right: 20) 设置边距
- Radio 单选按钮
- RadioOptions 一组按钮
- RichText 富文本标签
- TextSpan 富文本标签中的某一段落
项目插件
sdk: ">=2.11.0 <3.0.0" #适配空安全(允许关闭空安全)
cupertino_icons: ^1.0.2
shake_animation_widget: ^2.1.2 #底部向上动画弹出
date_format: ^1.0.9 #格式化时间的库
intl: ^0.16.1 #格式化时间的库
sqflite: ^1.1.3 #数据库
flutter_datetime_picker: 1.5.1 #时间选择器
audioplayers: ^0.16.1 #音频插件
flutter_echart: ^1.0.0 #图表插件
dio: ^3.0.0 #网络请求
tencent_kit: ^2.1.0 #腾讯插件
circle_progress: ^0.0.1 #倒计时进度条
本人项目细节
最终效果
登录界面雪花
步骤:
- 创建一个集合用来保存气泡生成随机数
- 创建动画控制器
- 执行刷新监听
- 开启气泡的运动
- initData 初始化 (获取随机透明度白色)(随机位置,半径,下落速度)
- 创建画布绘制