1 背景
目前有个任务,想将客户端的组件做成动态化,可配置。动态化可配置方案,基本有三种实现方式:
1.1 native实现
native
实现,就是数据类型驱动方式。android
原生编写模板,然后根据服务端返回的每个数据的type
来区分使用哪个模板。大模块可配置,小模块也需要可配置。
优点:加载渲染速度较快。
缺点:不够灵活,增加新的模板需要发布新的Android
版本。
1.2 H5实现
使用H5的优点:
- 一套代码两个平台上运行,既可以在
Android
上运行,也可以在IOS
上运行 - 使用
H5+CSS3+JS
可以开发出非常优秀的产品,如:饼图,柱图,雷达图等,可以做出的效果非常绚丽,开发成本较低,开发效率高。如果使用Android
或IOS
做出这样的效果,即使SDK
自带类似这样的控件,效果也不是很好。 - 产品改动,无需频繁版本升级。更改页面内容,只需要接口请求后台,通过url来加载服务端的H5页面,无需重新更新apk,用户无感知。
缺点:
- 相对于原生来说,稍微耗费流量,页面加载时可能稍慢。
虽然H5可以实现,奈何自己不想写H5代码
1.3 FlutterWeb实现
使用FlutterWeb
方式实现,原生通过webview
加载flutterweb
,flutterweb
代码放在服务端。
使用Flutter
优势:
- 一套代码两个平台上运行,既可以在
Android
上运行,也可以在IOS
上运行 - 使用谷歌自己的Skia渲染引擎,Android自带Skia引擎,iOS平台上Flutter也会把Skia引擎打包到APP中,实现高效渲染。
- 目前有非常丰富的视图组件,包括Android上常用的材料设计(Material Design)的UI风格,和
iOS
风格(Cupertino)。由于其渲染不依赖各平台相关组件,所以运行在不同平台上的效果是一致的。 - FlutterWeb支持Web,可编译成js文件,然后部署到服务端。所以产品改动,无需频繁版本升级。
缺点: - 相对于原生来说,稍微耗费流量,页面加载时可能稍慢。
FlutterWeb实现模型
Android原生这端不需要引入Flutter的sdk,通过WebView进行加载,所以Android原生与Flutter之间的交互,通过中间部分js来进行交互。交互方式可见【Flutter】Android原生WebView(非Flutter WebView)与FlutterWeb交互
中间需要js进行中转交互,上述图细分为
【Flutter】FlutterWeb与Js交互
实现方式
上述搜索框是在native这边,下面内容是flutter web内容,通过原生的webview加载。
数据交互的方式有两种:
- 后台返回Json数据以及Html标签数据,在Flutter端组装成带数据的Html标签,然后解析成Flutter组件
- 后台返回Json数据,在Flutter端根据Json数据中的样式type来动态拼接html标签,然后再解析成Flutter组件
上述两种方式的数据传递都是:点击搜索后,后台返回数据,webview将数据传递到flutterweb的js中,然后通过js将数据传递到flutter代码中。点击flutter页面的某些数据,会将点击的数据传递到native这边,然后再进行搜索,重新将数据传递到flutter页面,然后更新flutter。这涉及到原生调用js,js调用原生,Flutter调用js,js调用原生。
【Flutter】Android原生WebView(非Flutter WebView)与FlutterWeb交互实质上是native调用js,js调用native;【Flutter】FlutterWeb与Js交互是Flutter调用js,js调用原生。
两种方式抉择:
第一种方式优点:
- 模版粒度比较细,模版与模版之间可以动态组合。
- 所有小模版一旦定义完成,增加新的字段或者删除新的字段不需要更改html标签和Flutter代码,实现完全动态可配置,除非增加新的模版,才需要更改组装html标签的代码。
缺点:
- html样式组装在Flutter端,如果增加新的模版,还是需要更改Flutter端的代码。
- 为了配合动态可配置,后台返回数据需要增加许多额外字段,比如模版类型type。
第二种方式优点:
- html标签样式由后台返回,与Flutter分离。
- html标签增加新的字段或样式,不需要更改Flutter代码。
- 后台返回的Json没有额外的其它字段
- 后台可以事先预览要展示的模版
缺点:
- 增加新的字段或样式,都要手动更改html标签
- html标签中的占位数据要与Json返回的数据的格式要一一对应
其实根据上述描述,完全可以使用h5来写,但本人H5基础薄弱,不想写H5,而不在Flutter端进行数据请求,而是通过native端来传递的理由如下:
- 几个小页面,不想引入大量框架,如网络框架等等
- 最关键的是,我是个flutter小白,这个任务自己一个人写,没有其它flutter大佬可请教,不想弄得太复杂。
第一种方案交互模型如下:
上述方案好处:html标签类型解析成Flutter控件是自动完成的,如果增加或减少某个字段,不用更改Flutter控件显示部分代码,只需要更爱html标签拼接部分即可。
根据模版类型来自动生成html的标签字符串,比如:
模版一:一行显示两个文本,一个标题,一个内容,如下所示
在垂直方向增加条数不会更改到Android代码,它会自动生成行文本显示,实现了可配置。
模版二:格式相似的展示方式。如下所示,都是文本加空格的展示方式。
这一类样式相同,可以在垂直或水平方向随意增加相同格式而不用改动Android代码,实现了可配置。
模版三:表格类型,如下所示:
表格类型可以增加一行,或者增加一列而不用改动Android代码,实现了可配置。
上述可以通过模版来灵活配置各种查询页面,配置由后台接口返回的数据控制,Android端不用更改代码,但如果增加一个模版类型,则需要更改Android端代码。组合示例如下:
代码就不贴了,直接看github源码吧:
第二种方案的交互如下:
与第一种方式类似,只是html标签数据来源以及填充不一样。
后台返回的html标签数据如下(仅仅示例):
<p>[person-0-name]</p>
后台返回的Json数据如下:
{
"person":[
{
"name":"张三",
"age":19,
"sex":"男"
},
{
"name":"李四",
"age":21,
"sex":"男"
}
]
}
Flutter端组装:
//jsonstr是上述的json字符串,json必须跟html标签中占位的对象一致。
Map<String, dynamic> json = jsonDecode(jsonstr);
//然后解析html字符串,将真实数据替换[person-0-name]
......
然后使用flutter_html来解析:
//str是上面html字符串
Widget html = Html(data: str)
缺点:上述方式要自己写html字符解析类,非常的麻烦。flutter_html并不支持所有的html标签和css样式,交互或样式比较麻烦的需要使用自定义标签的方式。
最终没有使用FlutterWeb加Html的方式,使用的是Flutter加Html。