Flutter
前言
距离上一篇博客已经过了很长时间了,这次在做公司项目中又遇到了新的问题,决定还是写出来看看各位大神对此有什么看法,分享一下各位的想法。
问题
首先,公司项目的框架是由Flutter去编写的,最初的框架是由uniapp框架来做的,但是uniapp在客户端的性能懂得都懂。。。这里就不过多赘述,所以呢,是从uniapp框架迁移到flutter,但是由于项目周期的原因,最终采取的方式是flutter中混入uniapp,也就是让uniapp以H5的形式混入到flutter代码中,相当于在flutter中打开一个webview
,那么就一定会涉及到通信问题
。
那么客户端和h5通信有哪些方式呢?
- nativeApi
- window.postMessage
- localStrorage
- ...
nativeApi:其实就是客户端写一个函数,然后放在全局环境中,让环境中的h5去调用函数,以此来沟通
window.postMessage:这种方式比较常用于客户端向h5端传递数据,然后h5在页面中进行监听,以此获取数据
实际在开发中,方法都是混合使用的,比如我客户端传递数据使用postMessage
给h5,h5通过客户端提前在当前环境注入的方法去调用native方法
传递数据回给客户端,这种方式都一定是异步的
,实际上flutter跟原生层也是异步的
,异步肯定就会有延迟。
回到今天的重点问题,就是数据格式的问题,一般来说,客户端传递给h5数据,都会经过jsonEncode一次变成String类型的数据,然后再到h5层进行jsonDecode
。
实际代码大致如下:
客户端层:
bash
String data = jsonEncode(result);
await _controller.evaluateJavascript(
source: "window.postMessage({data:'$data'},'*')");
h5层:
bash
window.addEventListener('message', (event) => {
event.data
})
当然,实际上还会更复杂一些,会有一些通信规范和作用范围。
问题是什么呢 ?如果这个数据中存在双引号会怎么样?
双引号问题
可能觉得这种东西没有什么问题,我也大意了没有闪,正常json数据格式大家都很清楚,问题是如果你的数据是用户可以自由输入的,那就涉及格式过滤
的问题,比如各种特殊的符号,换行符、制表符等等,这种东西在编码的时候可能没问题,因为但凡能存入数据库
的都是处理了的,进行编码都会添加一个反斜杠
去处理。
举个例子:
bash
//如果你的数据是这样的
//用户的数据的xxxx"
String userData = "xxxxxx""
//那么入库的时候会变成
String userData = "xxxxxx\""
这是为了正确的编码和解码,加上反斜杠到客户端解码的时候会进行转译,最终还是显示一个双引号。
所以你是一对一的,比如客户端------后端
,那应该是没问题的,但是如果你的项目是这种后端------客户端------h5端
,数据多传一层,可能会遇到这个问题。
当数据到flutter层,flutter有进行了一次编码,此时还是有反斜杠的,但是到h5层会被转译,到h5的时候,此时的json格式就有问题了,变成
bash
string aa = " " "
双引号和双引号括起来是一段内容,但是后面又多了一个双引号,因为这个内容是用户输入的,用户当然可以随意输入。
问题代码:
bash
String data = jsonEncode(result);
await _controller.evaluateJavascript(
source: "window.postMessage({data:'$data'},'*')");
此时data里面的数据还是存在反斜杠的,但是postMessage之后,到h5层反斜杠丢了,json解析失败了。
flutter层如果内容存在反斜杠,decode会被转译,但是encode又会还原回来,这是正确的,没有任何问题。
但是如果传递数据给h5的时候,如果被丢弃掉,就会解析失败,所以我这么处理了:
bash
String data = jsonEncode(result);
data = data
.replaceAll(r'\', r'\\') //将单反斜杠替换为双反斜杠
.replaceAll(RegExp(r"(?<!\\)'"), r"\'"); //将单引号替换为单引号加反斜杠
当然可能还有更好的方法,欢迎在下面留言。
这样哪怕传递过去丢了一个,还会有一个反斜杠,到h5端转译依旧可以成功转译,但是仅限于用户可以自由输入的数据
。
比如你如果传递数据是用户数据或者固定格式的数据,你不能这么做,这样会传递错误的数据。
请求数据问题
前面说了,如果你是类似这种混合开发的项目,那么肯定也会有请求数据的问题,当然我们的请求往往也涉及加解密,那么这个请求究竟是放到客户端来做还是h5端来做:
- 如果是放到客户端来做:
就是h5发起请求通知客户端请求数据,客户端请求数据成功之后再把数据传递回h5端,这种方式如果数据量比较大 的情况,那么性能和效率也比较差 ,当然还涉及到请求没办法落地 的情况,就是h5发起请求,但是突然页面被掐了,请求还在处理但是没办法接收,导致这个请求一直在天上飞,资源释放不了,这是很可怕的事情,意味着请求是不可控的。
- 请求放到h5端去做
那么客户端就只充当一个加解密的工具,请求可控,但是这里面又涉及异步和延迟的问题
h5端发起请求,将数据丢给客户端去加密回传给h5去请求,响应之后又丢回给客户端去解密后回传给h5,来回总共4次,数据量比较大,实际上性能和效率也会差,甚至如果其中一个环节出问题,可能连回调都没有。
所以这两种方式在数据量比较大的情况,性能都不好,但是呢还是建议在h5端去做请求,因为至少请求是可控的
,那么就需要做好回调和沟通的处理。
要想兼顾性能又想兼顾开发周期,这是一件很矛盾的事情,往往都是需要舍弃的,这里就不过多赘述。
总结
千万不要相信用户的任何数据,用户数据是不可信的,一定做好校验和过滤。开发往往都是在舍弃的过程,我们都是在寻求一个平衡的方法。