写在前面
在做Flutter项目,我之前从事的是iOS开发,以object-C为主,Swift为辅。对Flutter也是从小白开始,因此这个过程中我踩过的坑,对于即将入坑的开发者来说还是具有普遍的先行者意义。希望各位读者,可以从中受到启发,从而绕过某些坑,在Flutter的开发之路上走得更快更稳健,那么也是我这篇文章最大的作用了。
价值论与方法论
相信大家都清楚,无论是object-C还是Swift,都是一种命令式编程。因此在我前几年的开发过程中,会被该语言特性潜移默化的塑造,脑子里的思维模型完全是被驯化成面向过程的。即:面对一个功能点,我马上想到的是我要得到这个结果,那么编译器你应该按照1、2、3点一步一步来做,先做什么,再做什么,最后做什么。
但是Flutter完全不同,它是一种声明式编程。它要得到某个结果,只需要告诉编译器应该做什么,但是不指定具体要怎么做。
正是由于这种思维定势的转换,是我首先需要克服的最大障碍。就像一个对孩子事事操心了18年的老父亲,突然在孩子成年后,不能再给出具体方法论,而是只能指出价值论的转变。期间的不适应是必须的,但是需要适应,需要适应这种不适应。
如果这种思维转换过来了,那么接下来就是单独面对这门语言的问题了。
工欲善其事必先利其器
开发工具:Vscode,Android Studio
利用Android Studio开发工具,预先设置快捷指令,可以让我们后期的开发过程事半功倍。下面我给出自己使用比较频繁的供大家参考。P.S.如果快捷指令有出入,各读者可以在自己的Android Studio上打开Preferences自行设置。
代码行复制:cmd+ a
查找文件:cmd +shift+ o/a
动态模式:cmd + j
代码上下移动:alt +shift+ up/down
代码展示/折叠:cmd + +/-
代码对齐:ctrl + alt + l
代码包裹:option(alt) + enter
statelessWidget转statefulWidget:option(alt) + enter
将build出来的Widget抽取到单独的widget中:option(alt) + enter + w
抽象类的实现类,方法的具体实现:command+ alt + B
格式化:command+ option(alt) + l
快速生成getter,setter,toString,constructor:command+ n
Dart先行
Dart是一种开源的通用编程语言。它最初由Google开发,后来被ECMA批准为标准。Dart是一种新的编程语言,适用于服务器和浏览器,现也被谷歌应用在Flutter中。
1.在线执行脚本:
可以使用https://dartpad.dartlang.org/上的在线编辑器在线运行测试脚本。
2.Dart标识符:
标识符是程序中元素的名称,如变量,函数等。标识符的规则是 -
标识符可以包括字符和数字。但是,标识符不能以数字开头。
除下划线(_)或美元符号($)外,标识符不能包含特殊符号。
标识符不能是关键字。
它们必须是唯一的。
标识符区分大小写。
标识符不能包含空格。
3.Dart数字方法:
abs:返回数字的绝对值
ceil:返回不小于该数字的最小整数
compareTo:将此与其他数字进行比较
floor:返回不大于当前数字的最大整数
remainder:除以两个数后,返回截断的余数
round:返回最接近当前数字的整数
toDouble:返回数字的double等效值
toInt:返回数字的int等效值
toString:返回数字的字符串等效表示形式
4.Dart函数定义:
function_name() {
statements
}
或者
void function_name() {
statements
}
void关键字表示该函数不向调用者返回任何值。
5.级联运算符(..)
class Student {
void test_method() {
print("This is a test method");
}
voidtest_method1() {
print("This is a test method1");
}
}
void main() {
new Student()
..test_method()
..test_method1();
}
级联(..)运算符可用于通过对象发出一系列调用。
更多的Dart语法学习,推荐直通车:
https://www.yiibai.com/dart
Flutter随后
中心思想:万物皆Widget
在学习过程中,我做了Flutter跟OC的等价:
MaterialApp ~ rootViewController
Scaffold ~ UIViewController
Widget ~ UIView
ListView ~ UITableView
GridView ~ UICollectionView
1.生命周期
先学习statefulWidget生命周期的意义:初始化数据,状态;网络请求;事件监听;内存管理等;
widget的constructor(init)方法:
构造函数widget的createState()方法
state的constructor()构造方法
state的initState()方法,必须调用 super.initState()
state的didChangeDependencies()方法
state的build()方法
state的dispose()销毁方法
注:
didUpdateWidget方法:当父类的结构发生改变时,则该方法会调用。
生命周期复杂版:state中的属性:dirty==true会调用build;mounted,是state内部属性;
clean表示当前build出来的widget,下次重绘时不需要重build;
创建
State 初始化时会依次执行 :构造方法 -> initState -> didChangeDependencies -> build,随后完成页面渲染。
更新
Widget 的状态更新,主要由 3 个方法触发:setState、didChangeDependencies 与 didUpdateWidget。
销毁
组件销毁相对比较简单。比如组件被移除,或是页面销毁的时候,系统会调用 deactivate 和 dispose 这两个方法,来移除或销毁组件。
获取屏幕尺寸的方法:
MediaQuery.of(context).size
MediaQuery.of(context).size=window.physicalSize/window.devicePixelRatio
2.Flutter与Native通信
Flutter定义了三种不同类型的Channel:
BasicMessageChannel:用于传递字符串和半结构化的信息,持续通信,收到消息后可以回复此次消息。
MethodChannel:用于传递方法调用,一次性通信。比如拍照。
EventChannel:用于数据流通信,持续通信,收到消息后无法回复此次消息,通常用于Native向Dart的通信。比如:手机电量变化,陀螺仪,传感器,网络变化等。
注:
在Flutter中,Native向Dart传递消息可以通过BasicMessageChannel或者EventChannel都可以实现。
在Flutter中,Dart向Native传递消息可以通过BasicMessageChannel或者MethodChannel都可以实现。
3.Widget的显示与隐藏
AnimatedOpacity(opacity: 1);
Offstage(offstage: ture);
Size为0的占位container
4.去掉水波纹或者高亮效果
theme:ThemeData(highlightColor:Colors.transparent,)
5.Flutter动画
Animation抽象类,监听动画值的改变,监听状态改变,value,status
AnimationController继承自Animation,vsycn:同步信号(this -> with SingleTickerProviderStateMixin) forward()向前执行动画 reverse()反转执行动画
CurvedAnimation:设置动画执行的速率(速度曲线)
Tween:设置动画执行的value范围。begin开始值 end结束值
1.创建AnimationController_controller = AnimationController( vsync: this, duration: Duration(seconds: 2))
2.设置Curve的值 _animation = CurvedAnimation(parent: _controller, curve: Curves.linear);
3.Tween _sizeAnim = Tween(begin: 50.0, end: 150.0).animate(_animation);
4.监听值的状态改变_controller.addStatusListener((status) { if (status == AnimationStatus.completed) { _controller.reverse() }})
6.路由
路由的概念由来已久,包括网络路由,后端路由,到现在流行的前端路由。
无论路由的概念如何应用,它的核心是一个:路由映射表。比如,名字detail映射到DetailPage页面等。
在Flutter中,路由管理主要有两个类:Route, Navigator
Route:这是一个应用程序抽象的屏幕或者页面。一个页面要想被路由统一管理,必须包装到路由管理。
MaterialPageRoute在不同平台有不同的表现。当然,iOS平台我们也可以使用CupertinoPageRoute.
Navigator:这是一个管理路由的widget。管理所有的Route的Widget,通过一个栈来进行管理的。开发中不需要手动创建一个Navigator,开发中使用的MaterialApp,CupertinoApp,WidgetsApp默认是有插入Navigator的。
以上两种widget对应Flutter中实现页面导航的有两种选择:
—具体指定一个由路由名构成的Map。(MaterialApp)
—直接跳转到一个路由。(WidgetApp)
例如:
MaterialApp(routes:{‘/a’:(BuildContext ctx) =>MyPage(title:’page A’)})通过把路由的名字push给一个Navigator来跳转:Navigator.of(context).pushNamed(‘/a’);还可以使用Navigator的push方法。以下示例中,MaterailPageRoute widget是一种模板路由,它根据平台自适应替换整个页面。Navigator.push(context, MaterialPageRoute(builder:(BuilderContext context) =>UsualNavscreen()));
Future result = Navigator.of(context).push(MaterialPageRoute( builder(ctx) {returnHYFindPage() } )); result.then((res) { })//用于接收下级页面传回来的值 下一个页面取出数据finaldata= ModalRoute.of(context).settings.argumentsasHYModel;
onGenerateRoute:(setting) {if(setting.name == @“one”) { }}
onUnknownRoute:(settings) { 跳转到未知页面 }willPopScope(onWillPop: () {returnFuture.value(ture)} child: Scaffold())
如何获取路由跳转返回的结果?
Mapresult =awaitNavigator.of(context).pushNamed(‘/a’);Navigator.of(context).pop({“lat”:123, “lon”:234});
Flutter第三方插件
轮播插件:Flutter-swiper
屏幕适配插件:flutter_screenUtil
网络请求库:flutter_dio
打电话,发邮件插件 :url_launcher
上拉加载下拉刷新库:flutter_easyrefresh
位置信息GPS插件:geolocator
相册与相机插件:image_picker
本地存储插件:SharedPreferences Plugin
访问数据库的插件:SQFlite
唤起第三方登录的插件:flutter_facebook_login
推送通知的插件:firebase_messaging
使用Firebase的插件:firebase plugin
关于Flutter直通车
变更记录:https://github.com/flutter/flutter/wiki/Changelog
公告:https://groups.google.com/g/flutter-announce?pli=1
博客:http://www.devio.org/tags/#Flutter http://www.imooc.com/t/4951150#article
第三方库查找:https://pub.dartlang.org/Flutter
官方仓库:https://github.com/flutterFlutter
官方文档:https://flutter.dev/Flutter
官方讨论邮件:https://groups.google.com/forum/#!forum/flutter-devFlutter
问题&方案:
Google:https://www.google.com
stackoverflow:https://stackoverflow.com
官库-issue:https://github.com/flutter/flutter/issues
Flutter第三方库:https://dart.dev/
网络请求测试:https://httpbin.org/
Flutter中文网:https://flutterchina.club/cookbook/
Flutter SDK:https://api.flutter.dev/
数据转换模型:https://app.quicktype.io/
写在最后
由于我也是刚入坑不久,难免挂一漏万,期间如果有错误,希望各位读者雅正。先在此谢过!