初识flutter
|偶然看见了移动端跨平台开发的深度解析这篇文章,里面提到的React-Native和weex或多或少都有了解,关于Flutter却了解甚少,于是决定体验一下。这篇文章主要用于初步尝试flutter开发的整理,包括开发步骤和遇见的一些问题。
在学习过程中写了一个练手的demo,放在github上了~
<!--more-->
参考文档
1. 准备工作
1.1. 安装
网上有大把教程进行安装,这里只是简单描述一下步骤就行了
- 下载对应环境的flutter SDK,解压到本地
- 配置flutter到环境变量,确保flutter命令可以使用
- 运行
flutter doctor
检测开发环境 - 欧了~
1.2. 语言
flutter采用Dart作为开发语言,关于Dart的相关语法,可以先看一下这篇教程。
Dart是一门很有趣的语言,在VSCode中安装flutter插件后,就可以体验代码高亮、语法补全等功能了。如果使用Android Studio,还需要安装Dart插件,配置flutter的SDK路径等工作。
貌似Dart还可以编译成JavaScript的代码,这个后面再研究下~
2. 部件
widget 部件是每个Flutter应用程序的基本构建块,通过组合不同的 Widget,来实现我们用户交互界面,这跟Vue中的Components十分相似。
2.1. 无状态部件和有状态部件
widget分为两种
- StatelessWidget,只用于展示信息,无用户交互行为
- StatefulWidget,可以通过改变状态(数据)使得UI发生变化,可以包含用户交互
flutter的部件也是有生命周期的,大致生命周期可以分为
initState : 初始化widget的时候调用,只会调用一次。
build : 初始化之后开始绘制界面,当setState触发的时候会再次被调用
didUpdateWidget : 当触发setState时,会被调用
dispose : 页面销毁的时候调用
无状态部件和有状态部件的区别在于,StatelessWidget组件只会build绘制一次,而StatefulWidget主要状态发生改变,就会重新调用build方法,重新进行绘制。
2.2. 布局样式
Flutter中的布局样式与CSS中部分概念比较相似,如margin、padding、border等,尤其是CSS中的flex布局,在Flutter得到了有力的支持。
尽管概念比较相似,但是在flutter中为widget添加样式与CSS添加样式还是有很大区别的,我们知道伟大的W3C标准推荐“行为、样式、布局分离”,而在Flutter中
- 不是所有 Widget 都可以添加任意的样式属性,有的部件只有布局样式,有的部件只有展示样式
- 由于布局、样式和逻辑都一起书写到widget上,部件的嵌套可能就比较深~论两个空格缩进的重要性
- 由于Dart语言的关系,基本上所有的样式属性都不在支持以字符串的形式书写,而是必须创建特定类的实例或是使用 Flutter 中预先定义好的常量
本文最后会整理在开发中常见的一些部件,用作备忘。
3. UI调试
做web开发已经习惯了使用Chrome的F12调试大法来进行界面调试,在Flutter中有什么比较好的UI调试方法呢?
3.1. Android的Flutter inspector
在Android Studio中,可以使用内置的Flutter inspector来实现布局调试。详情可参考Flutter Widget Inspecto-官方文档
如图所示,在模拟器打开flutter应用后,可以通过选择器选择对应的部件,然后就可以查看对应的部件名称和布局属性等。
此外可以通过rendering.dart
包来调试布局,开启debugPaintSizeEnabled后可以在布局页面上看见很多箭头网格,了解大致的布局嵌套(虽然这个功能不太好用~)
import 'package:flutter/rendering.dart' show debugPaintSizeEnabled;
void main(){
debugPaintSizeEnabled = true;
runApp(new MaterialApp(
title: 'Fun',
home: new FunApp()
));
}
3.2. iOS真机调试
首先参考官方文档进行安装,需要配置环境变量啥的,以及XCode。
brew update
brew install --HEAD libimobiledevice
brew install ideviceinstaller ios-deploy cocoapods
pod setup
然后进行下面流程:
- 切换到项目目录,运行
open ios/Runner.xcworkspace
- 此时会打开xcode的runner,配置好开发证书,使用数据线连接iPhone真机
- 如果弹出“要信任此电脑吗?”的弹框,请选择“信任”
- 然后左上角,选择运行目标为Device->iPhone,点击运行,进行安装
- 稍等片刻,就能在手机上看见安装的app了~
- 个人账号需要在手机“设置”->“通用” -> “描述文件与设备管理”中信任开发者,然后才能打开程序
真机安装遇见的一个问题是: ListView滑动感觉比较卡顿。
这个貌似是是因为安装的debug的缘故,安装release包就可以体验如丝般顺滑的体验。
flutter build ios --release
然后重新open ios/Runner.xcworkspace
将release包安装在手机上即可。
3.3. Android真机
Android真机的安装要比iOS简单一点
- 通过数据线连接电脑,windows貌似需要安装USB驱动
- 手机开启“开发者模式”和“USB调试”选项
- 提示“是否允许USB调试”,选择“是”
真机安装后,就可以愉快地使用啦~
4. 遇见的问题
下面整理在项目中遇见的一些问题
4.1. 包引入路径错误导致代码报错
import 'package:flutter_app/app/view//detail.dart';
上面面路径多写了一个/
,导致无法调用正确的构造函数
No top-level method '' declared. Receiver: top-level,Tried calling: (12333)
这里原本调用的是
new TextDetailPage(12333)
但是奇怪的是调整该模块的构造函数,不传递参数,则又调用正常了
4.2. flutter命令被阻塞
在使用flutter doctor
或者打包iOS真机包的时候遇见提示
Waiting for another flutter command to release the startup lock
在使用了flutter命令或者程序异常退出后,可能会出现这种提示,这时需要等待其他flutter命令执行完毕,或者手动删除<YOUR FLUTTER FOLDER>/bin/cache/lockfile
文件
4.3. 本地图片资源加载失败
原来本地图片需要在pubsepc.yaml
中进行声明
flutter:
assets:
- assets/img/ic_main_tab_company_pre.png
- assets/img/ic_main_tab_my_pre.png
参考
### 解析JSON
解析json时报错
Unhandled exception: type 'List<dynamic>' is not a subtype of type 'List<JokeModel>'
static List<JokeModel> fromJson(String data) {
// 这里还需要注意 dart:io包里面的json是小写了,之前找到有示例代码是JSON会提示undefined
return json.decode(data)['data']
.map((obj) => JokeModel.fromMap(obj))
.toList();
}
这是因为默认map解析的List类型是List<dynamic>,解决办法是指定map类型
static List<JokeModel> fromJson(String data) {
return json.decode(data)['data']
.map<JokeModel>((obj) => JokeModel.fromMap(obj))
.toList();
}
此外手写Model也是比较麻烦的事情,应该有根据json模板快速生成model文件的方法。
参考:
5. 常见部件
这里整理了常见布局组件的一些属性值含义及使用方法,方便日后查询。
5.1. Container 容器
相关属性
- child,设置子组件
- alignment,子组件在该Container中的对齐方式
- constraints,约束,这个可以理解为css中的
max-width
和max-height
- transform,设置容器的矩阵变化,使用 Matrix4
- 盒子模型,需要注意的是flutter内组件均与css中
box-sizing:border-box
类似,同样的宽度,增加内边距会导致子组件的宽度减小- width、height,设置容器的宽高
- padding,设置内边距,使用EdgeInsets
- margin,设置外边距
- 背景
- color,纯色背景
- decoration,设置container的背景(如BoxDecoration),可以设置渐变啥的
- foregroundDecoration,前景色,需要注意前景色是在child之后绘制的
5.2. Row和Column 行与列
参考:
Column和Row的用法十分相似,区别在于主轴方向不同。
相关属性
- children,指定多个子元素
- mainAxisAlignment,子元素主轴上的排列规则,类似于CSS的
justify-content
- crossAxisAlignment,子元素在纵轴上的对齐规则,类似于
align-items
- direction,指定主轴的方向
注意事项
- 如果需要子元素可以扩张(类似于css中的flex:1属性),需要通过
Expand
组件包裹该子组件
5.3. Text 文本
构造方法
new Text(data, options)
new Text.rich(new TextSpan)
相关属性
- style,使用TextStyle类,里面的属性与CSS比较相似
- inherit,是否继承字体样式
- color,字体颜色
- fontFamily,字体
- fontSize,字体大小
- fontWeight,字体粗细
- fontStyle,正常(normal)或者倾斜(italic)
- letterSpacing,字母间隙
- wordSpacing,单词间隙
- height,文本高度
- locale,区域设置,这个就有点懵了
- decoration,文本装饰,加个下划线、中划线啥的
- decorationColor,文本装饰颜色
- decorationStyle,文本装饰风格
- textAlign,文字对齐方式,这个是文字换行时,多行文字时的对齐方式
- textDirection,文本方向,只处理中英文一般不需要这个参数
- softWrap,是否自动换行
- overflow,文字超出屏幕时的处理方式,如截断、省略号、渐隐等
- maxLinex,最大行数设置
- TextSpan,在一个Text.rich中防止多个独立的文本
5.4. Image 图片
构造方法
new Image(); // 需要实现ImageProvider 并制定image参数
new Image.asset(); // 资源图片
new Image.file(); // 本地图片
new Image.network(); // 网络图片
new Image.memory(); // Uint8List图片
相关属性
- width、height,图片容器的宽高
- fit,源图片的填充规则,使用BoxFit对应属性
- color、colorBlendMode,指定图片的混合模式,类似于css中的滤镜
- repeat,当图片容器尺寸大于图片本身尺寸时的重复规则,类似于css中的background-repeat
- centerSlice,定义图片的拉伸 类似于Android中点9图的拉伸位置
- gaplessPlayback,图片资源ImageProvider变化时,在重新加载图片的过程中,原图片是否保留展示
5.5. TextField 文本输入框
参考:
相关属性
- style,文本样式,同Text的style属性
- dectoration,可以通过InputDecoration来添加一个标签、图标、提示文字和错误文本,placeholder也是在这里设置的
- controller,文本编辑控制器TextEditingController的实例,可以用来获取用户输入
- onChanged,监听输入框变化,也可以用来获取用户输入
- maxLength,最大长度;maxLines,最大行数
- obscureText,设置是否为密码类型
- inputFormatters,输入类型的格式
- onSubmitted,内容提交时的回调