背景
该项目为毕业的课程设计,针对校园信息的处理,开发一款具有针对性的APP,来完成校园内部的信息共享与传递。同时,也是作为初步入门flutter的小项目吧,当然了,这也是我本人第一次接触移动端开发。实不相瞒,很喜欢APP开发,于是,自己就开始琢磨flutter,为什么没有选择原生Android呢,主要还是因为,对于UI的布局渲染能力有限,会难许多吧(个人理解啦)
所运用到的主要技术与框架
- 后端则采用了java语言来编写,使用Spring boot来搭建项目,其他技术还有,aliSMS,JPush,Redis
- 移动端主要采用了谷歌的跨平台框架flutter,数据库有SQLLite
开发笔记(所遇BUG与解决方法,部分备忘信息)
flutte与服务端返回参数的对应关系:
通过flutter中的dio请求服务端接口获取参数时,flutter端中均采用 Map<String,dynamic> 类型来映射。当服务端某个参数返回为null时, 请求服务端返回的json数据时,在flutter中直接获取res属性则会出现属性不存在的异常,可通过Map的putIfAbsent(“res”, () => ‘’) 方法来解决。{ "statusCode":200, "message":"请求成功" "res":null }springboot整合Redis对redis.conf文件的配置
(1) 在本地开发过程中,需要连接在阿里云轻量应用服务器中的Redis服务,则需要修改redis.conf文件,如下所示:#1.监听所有网络连接请求(0.0.0.0在网络地址中表示所有地址) bind:0.0.0.0 #2绑定局域网中的指定IP(即配置访问Redis的IP白名单) bind:192.168.42.25(2) 为了远程Redis服务的安全,避免网络中的恶意攻击,建议在redis.conf文件中设置访问Redis服务的密码,用于客户端的连接认证
requirepass <密码>redis.conf文件中的bind代表绑定服务所在的本地的IP地址或者同一局域网中的IP,并不是连接Redis服务的IP地址在flutter中如果使用 GestureDetector 来包裹 column 组件(比如,通过空白区域来触发某种行为,并作出某种响应),会出现点击空白区域无效的情况,可以采用 ListView 来处理。
如果需要手动关闭 flutter 的 showModalBottomSheet() 在点击菜单或者按钮完成后执行 Navigator.pop(context); 操作,因为在flutter中模态框默认也是一个页面,只是为半透明而已。
在使用 Column 中使用 ListView 和 GridView 作为子组件的时候会报没有指定高度的异常信息,可以通过设置 ListView 和 GridView 的shrinkWrap=true(或者使用height来设置高度,这样做的话,就没办法做到元素自适应了,还可以通过 flexible 组件的包装来解决。
在 flutter 中使用 choiceclip 组件时,可以通过判断选中的列表是否包含当前的元素来实现选中与未选中,从而作出不同的UI展示。 同时,也可以在该组件的 onSelected 函数中,作出点击标签之后的数据刷新处理以及UI变化。
flutter 中使用wrap组件可以实现流动布局,当一行不足以所有放下子组件时,会自动换行进行适配处理。解决了在使用 row 组件,会出现子组件过多时,出现便捷溢出的问题。(应用场景:展示文章,商品的标签等)
在flutter中使用定位时可以有多种选择,通过点击按钮来获取位置信息的话,使用geolocater插件来实现较为简单与方便,并且提供了经纬度转为地理编码的API。当然你也可以选择高德、百度、谷歌等地图服务提供商的开发API,在 flutter 中几乎都可以找到对应的插件。
在MySQL中,sum聚合函数的结果与null数据发生运算时,结果为null。
在处理mybatis的集合映射关系时,即collection标签的使用,示例如下:
<reslutMap> <!--id标签一般用于表示主键列--> <id column="列名" property="属性名"/> <!--result标签用于普通列--> <result column="列名" property="属性名"/> <collection property="属性名" oftype="List集合中泛型的全类名"> <!--id标签一般用于表示主键列--> <id column="列名" property="属性名"/> <!--result标签用于普通列--> <result column="列名" property="属性名"/> </collection> </reslutMap>在mybatis使用更新语句,完成属性的动态更新时,可使用set标签将动态更新的判断语句放在标签体中,也可以使用trim标签指定suffix-override属性为英文逗号即可。他们的目的都是相同的为了去掉动态语句中多余的逗号。
在使用mybatis中的if语句时,偶尔出现以下异常信息:
Malformed OGNL expression: facultyName != null and != ‘’
,由于mybatis的if 标签是采用OGNL语法来解析表达式的,而这里的属性名 facultyName 中含有的lt和OGNL表达式中的小于符号同名,导致出现错误。最后,找到问题是由于空格的问题造成的,经过排查,确实是空格造成的问题。(粗心大意害死人呀***)在使用MySQL中的Count函数时,若不分组,最终将展示第一条记录,其他记录都会消失。
在 flutter 中 ListView 组件的children属性中不能存在为null的元素。
服务器返回的数据信息对 flutter 端来说都为Map类型,并且Map中的value均为*dynamic类型,后端若返回的是 List 数据,并且每个元素均为model时,可采用集合的
map<T>(function())API来指定泛型包装。向下面这样做即可:User user = (res as List).map<User>((m) => User.fromJson(m));在 flutter 有状态的数据组件中执行setState(function())之前,建议优先判断下mounted属性值是否为
true。判断当前组件是否已挂载在组件树中。flutter状态组件数据的动态数据初始化建议放在didChangeDependencies() 周期函数中来操作。
在 AndroidManifest.xml 的 application结点中 加入
android:usesCleartextTraffic="true"参数,可解决 flutter 在使用webView_flutter时网页无法打开的问题。showModalBottomSheet弹出层携带有输入框组件时,并且点击弹出层中组件页面跳转并回传结果时,在push前需要先pop, 否则会影响第二个页面的输入框组件的使用。(场景:在评论区输入评论信息,点击@按钮进入@页面并回传数据)
在 flutter 中可以
State with WidgetsBindingObserver来监听state的布局变化,并在didChangeMetrics() 中做出一些监听的动作。(场景:比如点击键盘中的收起按钮,然后关闭弹出的评论框输入区域)在 flutter 中实现评论功能时,针对评论输入框的弹出的问题,因为做了监听,所以窗口变换的时候,也就是点击遮罩会pop两次,第一次关闭弹窗,第二次会pop出详情页面,因为控制弹出框显示的状态量没有做出改变,才导致pop两次。通过za在showModalBottomSheet的then() 来解决这个问题。
记录一次严重的失误,这次失误导致我一天时间都在找错误。问了很多人,都没有得到解决,最后还是找到了问题的原因,在使用Dio的过程中,为了等你陆之后的每次请求都可以携带JWT Token串,手动调用自己封装的dio工具,导致了后续在使用Content-Type来指定提交的数据类型时,出现了每次请求的时候都没办法改变这个值,均为null的情况。只因为我在已封装的dio中手动设置鉴权的请求,然后就出现了Content-Type无效的问题。(
建议在需要鉴权信息的请求中,通过 options 参数来设置单次请求的请求头信息,也可以使用 provider 来共享这个数据,单独封装携带某种特有的请求头数据的请求 API)在spring boot中做图片上传时,被提示上传文件大小过大的异常并且上传失败等问题,只需要在 spring boot 的application.properties或者application.yaml重新设置文件上传大小的参数即可得到解决。
# 单文件的大小 spring.servlet.multipart.max-file-size=100MB # 请求的文件大小 spring.servlet.multipart.max-request-size=500MB12:23:27.348 [http-nio-8080-exec-4] WARN org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data;boundary=--dio-boundary-4285197029;charset=UTF-8' not supported]
产生上述异常的原因是:在使用多媒体上传信息时,在请求中使用了 @RequestBody 注解,都替换为 @RequestParam 注解即可。flutter 做多文件上传的时候,服务端无法获取文件时,是由于服务端的 Spring MVC 在对多文件上传 MultipartFile[] 数组映射时,参数名需要为"files[]"
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
产生上述异常的原因,有几个原因,(1)数据源的 URL 地址正确;(2)MySQL的JDBC的驱动包不正确。通过排查,均不是以上问题所造成的。最后发现是是因为在打包的过程中,对静态资源的打包处理配置有误,导致mybatis的xml文件没有一起打包导致的。像下面这样配置则会导致上述异常问题。<resources> <resource> <directory>src/main/java/resources</directory> <includes> <!--包含文件夹以及子文件夹下所有资源--> <include>**/*.*</include> </includes> </resource> </resources>解决办法:取消上述pom配置即可解决,默认是会将maven中的resource目录下的所有文件打包的在CentOS中使用
netstat -lnp | grep 8000查看指定端口的应用程序。(扩展:查看java 程序使用 jps命令)flutter 项目打为APK包
(1)生成 APK签名,Windows 命令行执行:
keytool -genkey -v -keystore E:/graduationDesign/back/flutter-apk-settting/Users/USER_NAME/key.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias key(2)然后执行APK打包命令:
flutter build apk执行 flutter run有时间出现卡在
Installing build\app\outputs\apk\app.apk的问题,导致真机安装完成并无法打开应用,同时无法找到已安装的flutter程序。使用以下两步即可解决:
(1)卸载已安装的 flutter 程序。adb uninstall com.example.application.name注: 当安装 flutter 程序时,出现了 签名不一致 的问题,造成无法安装的时候,将手机调节到调试模式,然后执以上命令即可完成卸载,便可以继续安装。(
首先保证电脑拥有adb服务)
(2)真机调试下安装 flutter 程序adb install C:\PathToYourProject\build\app\outputs\apk\app.apk小结
以上问题在实战过程中,所遇见的个别问题,做了一下记录。希望能够为开发过程中遇见同类问题的你,提供一点借鉴与帮助。当然问题远不止此,还有一些问题由于匆忙和时间的问题,在开发中忽视了,没有得到记录与总结,愿以后的自己多记录多成长。
因工作原因,也不怎么经常在线,最后在这里附上源码地址:
Server地址:https://github.com/H-Mongo/flutterAppServer
APP地址:https://github.com/H-Mongo/flutterAppServer
欢迎大家一起来共建该项目并指证不足