看个例子
Widget getX() {
if (condition1) {
return Text(‘Hello’);
} else if (condition2) {
return Container(
child: …
);
} else if (condition3) {
return Center(
child: …
);
}
…
}
Widget x = getX();
Center(
child: x // < — 如何处理这里的 x??
);
这里的child: x x是一个动态值,它的具体值需要在运行阶段才能确定,它可能是任意的Widget,如何在静态的wxml上处理这里动态的x?受Alita框架的启发,这里主要是借助于小程序template的动态性(template的is属性可以接受变量值)。有如下几步:
1、首先在遍历Dart源码AST结构的时候,会把每一个独立完整的“UI值”片段,对应到wxml的template, 比如上文 getX 里面的UI
…
2、在遇到 类似x 这种动态值的时候,固定的会生成一个template占位
3、在运行阶段,会根据getX
函数的运行结果来决定x映射的“UI值”,如果getX里面condition1为true,那么这里的templateName的值就是template001。具体的数据计算收集工作,参考下面要的 “渲染数据收集”过程。可以看出flutter_mp处理“值UI”方式,完全参考了Alita。
渲染数据收集
wxml结构的生成是在编译阶段就完成了,与它不同渲染数据是运行时的信息,随时会根据setState而改变。那么我们怎么收集出我们需要的渲染数据呢?
如果我们还是顺着Flutter的架构图,很难插入我们收集的钩子函数,另外Flutter的这个架构对于小程序来说太重了,下图红框里的这些过程对于小程序的渲染来说并不必要。最后由于最终的代码会被转化为js,而Flutter本身依赖的库里面很多是不支持转化js的,比如dart:ui等等。
所以我们实现了一个极简极简的Flutter小程序版本mini_flutter,在编译期我们会把所有对Flutter库的引用替换为mini_flutter, mini_flutter只存在到上图的Rendering阶段,这个Rendering的实现也是为小程序定制的, 在运行时期Rendering不断收集Widgets的信息。最终生成一个UI描述的JSON结构,这个结构就包含了上文所说的templateName, templateData,UI描述将会被下层小程序获得,用来渲染小程序UI,架构图如下:
Dart/JS:转化与互操作
Flutter的开发语言是Dart,而小程序的运行环境是浏览器,所以我们还需要把Dart编译为JavaScript代码。
在上文的编译打包阶段也提到这一点,这个过程主要是使用了Dart提供的dart2js工具,不过,针对小程序环境,生成的js代码仍需要做一些适配,另外虽然都是JS代码,dart2js生成的js和小程序原生js的运行环境却是隔离的,也就是说它们是不能共享变量,方法等等,它们各自在本身的"域"里执行。
这带来两个问题:
1、Widget 初始化 或者setState更新,生成的UI描述JSON,如何传递给小程序"域"呢?
2、相关渲染回调,事件的都发生在小程序"域",这些信息如何传递给Dart?
总结一下:Dart(最终会编译为JS)与小程序原生JS如何互操作?
解决这个问题主要是借助dart:js, package:js这两个库:
Dart操作JS
import ‘package:js/js.dart’;
@JS(“JSON.stringify”)
external stringify(String str);
这样当Dart代码调用stringify方法的时候,实际上会执行window.JSON.stringify方法
JS操作Dart
// dart注册
void main() {
context[‘dartHi’] = () {
print(‘dart hi!’);
};
}
// js 调用
window.dartHi()
这里只是简单说明Dart与JS的互操作,另外由于小程序的运行环境是阉割以后的浏览器环境,flutter_mp的实现还稍有不同。
总之,Dart与JS是可以互操作的,这样就打通了上层Flutter环境和下层小程序环境。
布局系统
Flutter的布局系统不同与css,但是和css颇相似。
在上文提到的Rendering阶段,会根据Widget的布局属性,类别,约束条件生成一个等效的css样式。注意这里边界约束是上下文相关的。比如一个没有宽高的Container实际大小,不仅和子元素相关,还和父元素传递过来的边界约束条件相关,这个其实是比较麻烦的,能不能把Flutter的Widget属性,边界约束完全用css表达,我们还在寻求有效的方案。
总结
和flutter_web一样,完全把Flutter所有特性渲染到小程序上是不可能的,一般我们觉得应该是部分页面,部分功能需要运行在小程序上,这样使用flutter_mp才是有意义的。
正如前文所说,flutter_mp还在很早期的阶段,如果你需要在生产环境实现小程序跨端开发,推荐使用我们成熟的RN转小程序项目Alita。
学习分享,共勉
题外话,之前一直不注意对知识的整理,导致很多知识点学习不系统,正好最近同事和我花了一个多月的时间整理出来一份Flutter全方面的学习资料,今天把它免费分享出来,希望能够帮助到陷入移动开发困局Android工程师朋友,尽早跟上新兴热点技术。这份资料包括Flutter学习PDF+架构视频+面试文档+项目实战(源码)也省的大家再去网上花时间找资料。点击我 前往免费领取
资料免费领取方式:转发+关注+点赞后,点击我 前往免费领取
重要的事说三遍,关注!关注!关注!
原文作者:京东云技术新知
原文链接:https://www.cnblogs.com/jdclouddeveloper/p/11686367.html
推荐学习资料
- 脑图
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
86367.html
推荐学习资料
- 脑图
[外链图片转存中…(img-fKajHOq6-1715313253798)]
[外链图片转存中…(img-B5cK6SD3-1715313253799)]
[外链图片转存中…(img-Q2eymABM-1715313253800)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!