用flutter开发后要打包时,需要对项目目录进行微调
1、android,要将keystore进行注册和设置,如果有开发中对minSdkVersion有过微调,这里就不用管了。毕竟每个项目都不一样,但keystore可以一样
其实就是一句:keytool -genkey -keyalg RSA -keysize 2048 -validity 36500 -keystore test.keystore -alias testalias
这里面看着keystore和alias,因为最终要在flutter里设置这两个玩意
OK,生成完后,在flutter项目的android下创建:key.properties,输入4行
XML/HTML代码
- storePassword=123456
- keyPassword=123456
- keyAlias=testalias
- storeFile=/Users/gouki/test.keystore
keyAlias,对应了刚才上面的-alias,storeFile,对应了实际路径,可以在项目外,反正只要能够访问得到。
然后修改build.gradle,参考 localProperties的写法,加入:
XML/HTML代码
- def keystorePropertiesFile = rootProject.file("key.properties")
- def keystoreProperties = new Properties()
- keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
然后找到buildTypes,会发现里面一有一句:signingConfig signingConfigs.debug,其实你搜索整个文件,都找不到signingConfigs这个节点。所以理所当然的,将debug改成release,在和buildTypes的同级,增加:
XML/HTML代码
- signingConfigs {
- release {
- keyAlias keystoreProperties['keyAlias']
- keyPassword keystoreProperties['keyPassword']
- storeFile file(keystoreProperties['storeFile'])
- storePassword keystoreProperties['storePassword']
- }
- }
保存,然后flutter build apk 即可。
Running Gradle task 'assembleRelease'... 43.0s
✓ Built build/app/outputs/flutter-apk/app-release.apk (32.9MB).
2、macos ,相对更方便了,如果没有特殊的调整,其实基本上在开发的时候都有修改过了,即:在macos/Runner下,修改DebugProfile.entitlements和Release.entitlements,增加:
XML/HTML代码
- <key>com.apple.security.network.server</key>
- <true/>
- <key>com.apple.security.network.client</key>
- <true/>
否则,读取不了网络。。
flutter build macos
---
最后打完后一看。。。我10M左右的assets,最终打完包:
android apk 32.9M
macos xxx.app 55.6M
项目完成,这是我第一次完整的写完一个flutter项目(还差一个自动更新)。之前都是用uniapp打包的。
代码还没有优化,当然其实在写的过程中已经反复过好几次了,有为了性能上的,有为了显示上的,但怎么说,完成比完美更重要。如果没有完成,天天完善,最后一个APP都出不来。。。完成了,还有机会去完善(虽然可能只是口号)。。。
在学习flutter的过程中,遇到了几个对我来说难度有点大的问题,比如swiper、弹出菜单(含子菜单)等。所幸都一一实现了。
swiper的实现相对比较简单,其实就相当于是两个模块:1、pagination 2、实际滚动内容
1的话其实相对简单,只是一个listview.generate就完事了,不过因为我们中间用了连接字符串,所以当屏幕大小可变时,这个连接字符串的长度就要可控。所以我用了 '--' * 100,然后限制maxLine=1,overflow =clip,就处理完了
2、最早没有采用滚动的时候,是使用了图片切换,这时候无论怎么做动画效果都没用,比如AnimatedContainer,无效;AnimatedController也没用。毕竟只是换了一个图片地址,容器大小都没变。所以最后还是尝试采用了SingleChildScrollView,然后复杂的就是做联动了。
做联动经历了3个小阶段
a. 点击pagination,采用_controller.animateTo,这样还有动画跳转,跳转到指定page页面。
b. 滑动图片时的手势操作,这个相对比较简单,我用了genstureDetector,只判断了横向的手指更新和滑动结束。更新的时候,只计算 delta.dx,即横向移动的距离,负值则页数减1,正值加1,这样一页页的跳转就完成了。
c.最复杂的就来了:因为我用的是macos的代码,前面是鼠标手势,如果用触摸板,那么刚才的手势就完全无效了,而且触摸板滚动的距离非常长可能一下子会有5~6页,整个下午就卡在这里。
第一次尝试,是用_controller.addListener(),确实可以看到 _controller.offset在移动,但addListener只能看到数值在变化,却无法判断停下来。
第二次尝试,是用_controller.position.isScrollingNotifier.addListener,这时候可以判断 !_controller.position.isScrollingNotifier.value,如果无值代表停下来。刚开始还OK,但如果一更新代码,再滚动,立即 报错,说_controller.positions.isNotEmpty 不正常。而且这个listener,是要放在:WidgetsBinding.instance?.addPostFrameCallback中的。所以暂时放弃
至此,全部完成。做个笔记~~~
出现标题的错误的原因,极大的可能是,页面中有多个ScrollView的组件,如:ListView,SingleChildScrollView,CustomScrollView,有同样的滚动方向,但是又没有ScrollController。
这时候只要在除了第一个出现的scrollview外的scrollview中,加入:primary:false,即可
参考:The provided ScrollController is currently attached to more than one ScrollPosition · Issue #93862 · flutter/flutter (github.com)
我在遇到这个问题的情况就是:
1、页面中有弹出菜单和子菜单,高度超过了1屏
2、点击子菜单出现详情的时候,也需要滚屏(部分内容)
因此,相当于一个页面出现了3个ScrollView,在没有加primary:false前,只要子菜单一弹出,就开始报错。在子菜单中加入:primary:false后,不再出错,但点击子菜单显示详情的时候,又出现了这个错误。
将子菜单和详情对应的scrollview中都加入primary:false后,问题 解决。
在使用flutter的http库请求API时,发现返回的数据均为乱码,例如这样:ä¸æµ·å¸é¿å®åºé¿å®è·¯1189å·æ¥ç¦å£«å¹¿åºä¸åº401-402
原来使用的是:json.decode(response.body),看来不能直接对字符串进行处理。所以还是安稳的改用:json.decode(utf8.decode(response.bodyBytes))
至此问题解决。
如题。实在买不到酒喝了,,把20年买的这两瓶酒也干掉了。心碎
以后也买不到了。所幸,它进了我的肠胃,也算是有一个好归宿了。。。