一、简介
1. 优点
2.缺点
二、环境搭建
1.sdk 配置
2.插件配置
3.镜像配置
三、混合开发
1.结构介绍和选型
2.创建项目 集成的两种方式
3.在android 中调用Flutter lib
4.通信(未写)
四、flutter(dart语法)
1.生命周期绑定
2.ui
3.图片处理
五、三方插件
六、自定义插件
简介:
Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。 Flutter可以与现有的代码一起工作(这个就是我们常说的混编模式),也可以单独编写一套全新的Flutter App。在全世界Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费、开源的。
目前国内大厂具有代表性的:闲鱼、京东、美团。他们也出了相对应的开发框架如闲鱼(flutter-boost)
下图是对目前主流跨平台开发语言工具包的对比:
从初步结论来看,Flutter 确实优于其他一些主流跨平台工具包。
优点:
1. 跨平台
提起flutter,最先谈的就是它的跨平台咯。
用dart语言编写,一套代码在android、ios上运行。相比于RN页面由前端写,flutter则是以一种新的形势出现,独立于android、ios、web;这样的好处是,前端也不会flutter,大家基本都在同一起跑线(个人感觉);
当demo在两个模拟器上都跑起来的时候还是很开心的,哈哈。
如果后面Fuchsia出来了,可以跨Fuchsia就更牛逼了。
2.性能和开发相关
flutter号称每秒60帧,性能上是媲美甚至是超过原生开发的;
这点因为我写的都是小demo,所以感觉不到快慢。github上clone别人的几个大一点的项目,跑出来效果基本上感觉不出是flutter写的,和原生的差不多;
关于热部署这点,其实算是和android的instant run类似。但是好像要快一些,比如改一下home里面的一些widget状态,热部署后秒更新ui,瞬间看到代码修改后的结果,还是挺猛的。大大提高了开发效率。不过就是有bug了,这个后面缺点再说。
上手后开发app还是挺快的。因为不管用什么开发,最后出来的app肯定是要和产品想要的一样。所以,熟悉了基本flutter开发流程后,android developer使用flutter开发app流程还是和原生大同小异的。ios不太清楚,但是听一个ios开发说,flutter语法以及开发特点上更像oc。不过android开发者比ios开发者的最明显的优势就是flutter支持androidStuido,却不支持xCode。
flutter 内置了很多东西。比如一些小控件图片资源,网络图片缓存啥的,用起来很方便。
dart语言特性。写list等数据结构、还有类似builder构造函数用起来挺爽的。
3.flutter和google的关系
这段时间大家都应该听说google和甲骨文公司的纠纷,以及前段时间欧盟android收费等消息。
android从java到提供kotlin开发,然后到现在flutter的出现。
然后就是新的google Fuchsia系统(统一android和chrome os),也是用dart语言开发,不确定是不是flutter。如果后面这个新的系统真的出来,并且可以在手机上跑,那么到时候移动端很可能是android ios Fuchsia三分天下了。
这里就有问题了(以下只是个人见解,以及一些危机意识):
现在每个公司除了跨平台,都有android、ios独立的开发小组,那么Fuchsia出来后呢?三个小组?然后发现flutter写的在三个系统都可以跑,那还有必要开三份工资吗?
或者说会保留一些原生开发,可能一些功能跨平台做不了,还是要每个原生系统自己去实现(模块的方式)。但是大部分还是跨平台去实现了。如果真是这样,那么如果只会android或者只会ios,到时候说不定真的会凉凉,难受啊马飞。
但是这也算是一个机会吧,如果Fuchsia真的火起来了,一些大厂或者针对海外市场的公司应该会去占领这个新的操作系统的市场。到时候只有小部分开发者会flutter,而你刚好在其中(熟练&精通),岂不是美滋滋。
4.其他实际一点的
今年GDD,闲鱼真是出彩,除了tensorflow lite的应用,flutter的应用也是超级厉害,感觉真是业界的领头羊。闲鱼的部分务模块已经用flutter接到原来的框架了,并且经受住了千万、亿级别的考验;说明这东西还是靠谱的。之前还看到知乎上的闲鱼技术官方号在招flutter开发,牛逼的可以去试一下。
现在一些公司的android招聘要求,已经把flutter作为和rn、weex一样的加分项了。
如果之前你没有系统的通过官方文档学习(比如学android、java是通过别人整理的资料:书籍、博客、视频等),可以用flutter中文网来练练手。英语过关的可以直接看英文版的。官方文档才是第一手资料,看别人整理过的东西,别人已经帮你踩过坑、思考过了,而且可能还表达的不全面。
大部分人都想成为垦荒者吧,互联网技术这块还是国外的先进一些。如果是一项新技术,应该是英文文档先出来,等整理成中文网站就慢一步了。如果再等国内大佬发博客、出书籍就更慢了。
缺点:
说说个人最近使用flutter后对flutter的一些吐槽吧
1. flutter的包体积比原生开发的大
会比android原生apk大一些。因为渲染引擎放到了app里面。
image.png
image.png
下面是apk(别人github上的项目,业务较少)体积:
image.png
(到目前由于经验较少,不确定业务量增大后,apk大小增长的速度是不是和原生的一致了。如果本来apk就有50多M,flutter引擎如果只是增加7M,一共60M,貌似也可以接受)
至于为什么要把引擎放到app里面,现在我也不懂。google了一下,看有人说应用程序中包含 C / C ++ 引擎和 Dart VM是为了应用程序直接使用本机指令集运行,不涉及任何解释器。
2.flutter的ui 刷新问题
每次重新绘制那一下,特别是列表滑动,android上稍微认真观察,就会发现会卡一下。ios不明显,android比较明显。闲鱼的详情页也有这种情况。
flutter ui的概念是every thing is widget,就连页面也是一个widget。widget又分有状态和无状态。
个人觉得吧,无状态的widget就是为了让Ui不要重新绘制。
猜测原因(没看过flutter的cpu proflier,纯属瞎BB):list滑动刷新通过有状态widegt来刷新状态(setState)来重新绘制页面造成的瞬间卡顿。
3.flutter是用代码布局,没有xml的概念,对android程序员不太友好
(demo是stackoverflow上的一个flutter使用相对布局的回答,然后答得太好直接被官网引用了,牛逼啊)
可能ios开发要好适应一些,但是android开发习惯了xml布局,刚开始接触可能不太适应(使用一阵子就习惯了)。
android里面看Ui布局,一般是通过xml来看大概的布局,虽然有时也会用代码动态管理ui,不过大部分还是习惯用xml布局。
比如下图:
flutter的布局是一层套一层,如果要使用复杂一点的布局,就得嵌套多层。下面的布局是list的一个小item。
image.png
刚开始是会觉得这个好麻烦,代码里面利用row包children,children里面有clumn包children,就像一颗ui结构树一样,然后每个树节点用类似builder模式传一些参数进去描述具体节点特征。(下图是官网上另一个demo的例子,直接copy过来示意一下,和这个demo不对应)
image.png
好消息是可能是因为dart和flutter的机制,虽然没有xml看ui结构,但是可以通过代码旁的结构树来查看。点击树里面的节点还能对应到具体的代码位置。还是挺不错的。
image.png
4.flutter有bug
热部署有时候有问题
虽然flutter的热部署很厉害,很好用,但是也有熄火的时候。
一种情况:
如果你的app是多个页面,如果当前页面在c,但是你改了其他页面的代码想看效果,这时候热部署完了之后还是在c页面的;你想看到其他页面修改后的效果,需要手动切到那个页面。这个可能跟flutter的一个页面也是属于widget有关。当然如果重新运行,他还是会从main函数入口开始重新执行初始化逻辑。
另外一种情况:
上面那种情况其实还可以接受。但是有时候热部署会突然卡住,然后一直卡在同步数据中,一般卡好一会儿。这时候因为在等待执行hot reload,所以也点击不了重新运行。
image.png
等一会就变成这个样子,然后就GG了,必须得重新关掉ide再打开。。。
flutter sdk会突然抽风
flutter有类似android gradle的管理叫pubspec.yaml
image.png
有时不小心点到flutter升级后,升级完就GG了。不知道是不是操作不当,然后之前能跑的项目就跑不了了。更正flutter doctor尝试也不行,最后只好把flutter sdk,flutter plugin,dart plugin全部清掉,又重新装一遍。
最奇怪的一次是昨天晚上还跑的好好地,今天白天去公司用androidStuido写android项目,完全没动flutter相关的东西,晚上回来就跑不了flutter项目了。各种查,找不到原因,又重新装了一次。
我每次都是用的github上flutter的dev分支,前前后后大概重装了3次,现在终于是稳定了。
5.学习成本不小
flutter算是一种新的开发方式,语言用dart开发,虽说dart很像很像java,但是有些细节和java不太一样,所以遇到的时候还是要去查一下。
然后就是flutter除了上面说的移除了xml的布局,纯粹用代码写布局外。flutter的控件这些还是要花时间去掌握。和android原生的用法不一样,相对布局的概念也有些差异。
flutter使用的异步线程也和java虚拟机不太一样。因为java里面栈才是线程私有的,堆和方法区是线程共享的,这就要考虑堆里面数据的多线程问题。但是flutter里面堆也是线程私有的,所以不用担心多线程。但是个人感觉如果不花时间去理解这种模式,后面肯定是会有问题的,虽然目前还没遇到(demo)。
之前也提到过,除非一个新项目全部用flutter写(也有可能一些功能要原生去实现)。老的项目里面用flutter,要用模块的形式接进去。就要涉及到flutter和android原生、ios原生相接。这就代表如果android去开发flutter,除了学习flutter,后面还是有概率要去看看ios的一些原生开发方式(理想情况是android+flutter和ios+flutter)。类似的接so库这些也不太一样
适配问题。而且虽说一套代码在android、ios上面跑,但是android、ios的风格是不一样的。有开发经验的都知道ui给的图,最明显的就是titleBar两端是不一样的。
一个是Material一个是Cupertino风格。现在我都是按照android的material风格写的,如果是做线上项目,肯定也要花时间去适配ios风格的。
二、环境搭建
1.sdk 配置
Android Studio 作为开发Flutter工具,该开发工具是Google 官方指定开发Android App的工具,目前支持Flutter 插件和Dart 插件。
下载方式
1、在git命令行下输入如下命令:
git clone -b alphahttps://github.com/flutter/flutter.git
注意: flutter的下载路径要全英文并且路径不能有空格!
2、Flutter SDK下载地址:
https://flutter.dev/docs/development/tools/sdk/releases?tab=macosflutter.dev
进入官网页面以后如下图:
画红框的地方可以根据当前自己使用系统选择不同平台Flutter SDK ,由于我这里是macOS 所以我选择如下图的SDK进行下载
这里有个议纯属个人建议:最好选择stable分支的SDK进行下载 并且不要选择最新版本由于Flutter SDK更新速度较快。
我们在开发项目中由于Flutter 整个生态还不完善所以有的功能会借助一些第三方plugs 去完成。而这三方plugs是造成不选择最新版本最直接的原因之一。由于最新版本发布有很多插件还没有同步编译所以问题出在兼容和版本稳定上。
2、下载完成解压Flutter SDK安装包到您想安装的目录下(目录位置没有要求):如
3、配置添加Flutter SDK下面bin目录里面相关工具到path中去
最后一定要记得保存,保存运行如下命令:
source ~/.bash_profile
在配置好上面path以后,我们需要手动关闭终端然后重新打开并运行如下命令:
flutter doctor -v
序号1:当前你安装的Flutter SDK 版本信息和Flutter 引擎版本还有Dart版本信息,由于Dart SDK已经捆绑在Flutter里面了。
序号2: 由于本人是Android开发所以这个暂停一下(留下节课继续更新)这个地方一般是需要在XCode上进行配置Flutter 环境
序号3、4: 作为开发者,开发工具先行,由于我的电脑上已经安装了Android studio 和IDEA 所以我这两个开发工具环境都已经配置好。
下面我们还可以继续运行命令如下:
flutter -h
注意点:如果您当前Flutter SDK不是最新版本会提示:
A new version of Flutter is available!
To update to the latest version, run "flutter upgrade".
一般不需要理会,除非您想升级到最新版本 可以直接运行:
如下:
2.插件配置
1.Flutter插件支持Flutter开发人员工作流程(运行,调试,热重载等)。
2.Dart插件提供了代码分析(代码验证,键入代码,完成代码等)。
3.Flutter Enhancement Suite Flutter代码增强提示
4.WidgetGenerator 自动生成Widget接口
5.flutter-img-sync自动同步照片路径
3.镜像配置
Flutter 社区
社区主镜像,采用多种方式同步 Flutter 开发者资源(推荐)。
$exportPUB_HOSTED_URL=https://pub.flutter-io.cn$exportFLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
上海交大 Linux 用户组
使用反向代理方式建立的 Flutter 镜像,数据与站源实时同步。 Pub API 返回值未做处理,可能造成无法访问的情况。
$exportPUB_HOSTED_URL=https://dart-pub.mirrors.sjtug.sjtu.edu.cn$exportFLUTTER_STORAGE_BASE_URL=https://mirrors.sjtug.sjtu.edu.cn
清华大学 TUNA 协会
定时与 Flutter 社区 Storage 镜像同步,Pub API 采取定时主动抓取策略,镜像配置了完善的失败回源策略(推荐)。
$exportPUB_HOSTED_URL=https://mirrors.tuna.tsinghua.edu.cn/dart-pub$exportFLUTTER_STORAGE_BASE_URL=https://mirrors.tuna.tsinghua.edu.cn/flutter
CNNIC
基于 TUNA 协会的镜像服务,数据策略与 TUNA 一致,通过非教育网的域名访问。
$exportPUB_HOSTED_URL=http://mirrors.cnnic.cn/dart-pub$exportFLUTTER_STORAGE_BASE_URL=http://mirrors.cnnic.cn/flutter
腾讯云开源镜像站
定时(每天凌晨)与 TUNA 协会镜像同步,数据有延迟,访问速度有待反馈。
$exportPUB_HOSTED_URL=https://mirrors.cloud.tencent.com/dart-pub$exportFLUTTER_STORAGE_BASE_URL=https://mirrors.cloud.tencent.com/flutter
三、混合开发
1.结构介绍和选型
一般来说混编方案有以下两种:
统一管理方案:将iOS工程和Android工程作为Flutter工程的子工程,由Flutter统一管理。
三端分离方案:iOS工程、Android工程、Flutter工程是三个单独的项目工程,将Flutter工程的编译产物作为iOS工程和Android工程的依赖模块,原有工程的管理模式不变,对原生工程没有侵入性,无需额外配置工作。
1. 统一管理方案
统一管理方案是只有一个项目工程,这样的好处是代码集中,可以很方便的进行项目开发,每个开发同学都可以进行iOS、Android和Flutter的开发。当然缺点也非常明显:
对原有项目的侵入性太大,项目对外部环境的依赖程度增加。
每个人本地都要装有自己端的开发环境(iOS/Android)和Flutter的开发环境,并且Flutter SDK版本要保持一致。
耦合度会越来越高。当项目越来越复杂后,整个项目的代码耦合度会越来越高,相关工具链耗时也会越来越长,导致开发效率降低。
2. 三端分离方案
三端分离方案是iOS、Android和Flutter分别作为三个独立项目存在,在远端各自有各自的代码仓库。这种方案需要单独创建Flutter项目,然后通过iOS(CocoaPods)和安卓的依赖管理工具将Flutter项目build出来的framework、资源包等放入Native工程以供使用。这种方式可以将iOS、Android和Flutter项目放在一个目录下面作为一个项目来管理,也可以不在同一目录下,关键是设置Flutter模块依赖时相对路径一定要设置正确,如下:
选型
2.创建项目 集成的两种方式
1、 新建Flutter项目,选择Flutter Module类型
通过Android Studio 选择File->New->New Flutter Project->Flutter Module创建。
通过命令行$ flutter create -t module my_flutter创建。
创建完成后,Flutter Module可正常运行到设备上。
2、 在Android项目中集成Flutter项目
在宿主项目app下的的build.gradle里面,android {} 下修改:
如何在原生项目中引入Flutter模块
方式一:主module通过模块依赖方式来依赖flutter
将flutter作为module,然后native主工程引入进来。这种方式适合参与人数比较少的项目,如果有多人协作开发的大型项目就不合适了,因为其他人首先要配置Flutter环境,而且团队里面其他人还要配置module的依赖,都要熟悉flutter,成本是很高的。
在工程的settings.gradle增加以下配置:
在app 的gradle里添加依赖:
弊端:
这种方式适合参与人数比较少的项目,如果有多人协作开发的大型项目就不合适了,因为其他人首先要配置Flutter环境,而且团队里面其他人还要配置module的依赖,都要熟悉flutter,成本是很高的。所以还需要以依赖jar/aar的方式来集成。
方式二:通过aar包引入
将Flutter module打包成aar文件:
进入根目录下的.android目录下执行./gradlew assembleRelease编译成功后会在.android/Flutter/build/outputs/aar/flutter-release.aar生成aar文件。 (此种方式生成的aar包之前还能用,当前版本会报错,稍后会提供通过使用fat-aar使用脚本打包方式)
注意:暂时以第一种方式集成,稍后在【二、Android原生以AAR形式集成Flutter项目】会详细讲解方式二的使用。
3.在android 中调用Flutter lib
在java中调用Flutter模块有两种方式:
--使用Flutter.createView API的方式
--使用FlutterFragment的方式
1、
2、
上面我们使用字符串“route1"来告诉Dart代码在Flutter视图中显示哪个小部件。Flutter模块项目的lib/main.dart文件需要通过window.defaultRouteName来获取Native指定要显示的路由名,以确定要创建哪个窗口小部件并传递给runApp:
3.在Android项目中调用flutter
1、在Android布局中添加占位符
2、添加调用Flutter的代码
FragmentTransaction tx=getSupportFragmentManager().beginTransaction();
tx.replace(R.id.someContainer, Flutter.createFragment("{name:'devio',dataList:['aa','bb','cc']}"));
tx.commit();
3、
运行结果:
点击test按钮后,加载flutter界面
4.
注:
1、在dart中通过window.defaultRouteName来获取Native传过来的参数
要使用window对象一定要导入包‘dart:ui’
在MyApp中作为参数传递给MyHomePage
在MyHomePage中,通过initParams展示了传递过来的内容
运行后结果
打包脚本
在项目根目录下创建打包脚本aar.sh,内容如下:
#!/bin/bash
# 初始化记录项目pwd
projectDir=`pwd`
# step 1 clean
echo 'clean old build'
find . -depth -name "build" | xargs rm -rf
cd ${projectDir} # 回到项目
rm -rf .android/Flutter/build
#flutter clean
# step 2 package get
echo 'packages get'
cd ${projectDir} # 回到项目
flutter packages get
# step 3 build aar,生成aar,然后上传到对应maven仓库
echo 'build aar'
cd ${projectDir}
flutter build apk
if [ $? -eq 0 ]; then
echo '打包成aar 成功!'
else
echo '打包成aar 失败!'
exit 1
fi
cd ${projectDir}/.android
./gradlew flutter:uploadArchives
if [ $? -eq 0 ]; then
echo 'uploadArchives 成功!'
else
echo 'uploadArchives 失败!'
exit 1
fi
echo '<<<<<<<<<<<<<<<<<<<<<<<<<< 打包成功,aar上传成功 >>>>>>>>>>>>>>>>>>>>>>>>>'
echo "打包成功 : flutter-release.aar, 本地仓库:${projectDir}/repo-local"
exit
在根目录下打开命令行,执行打包脚本即可:
$ ./aar.sh