用户
 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,登录网站

小程序社区 首页 教程 实战教程 查看内容

微信小程序开发技巧之双线程模式详解

Rolan 2021-1-12 11:07

和web页面UI渲染和脚本执行在一个单线程不同,小程序采用了双线程架构设计,将试图渲染与业务逻辑分别运行在两个不同的线程中

双线程模式是什么(what)

官网图镇场: 

和web页面UI渲染和脚本执行在一个单线程不同,小程序采用了双线程架构设计,将试图渲染与业务逻辑分别运行在两个不同的线程中

为什么使用双线程模式(why)

用web页面的困局
  1. 原生能力
    早在2015年,微信发布了一整套网页开发工具包JS-SDK, 通过开放原生功能API使得 Web 开发者都可以使用到微信的原生能力,例如拍摄、录音、语音识别、二维码等。但是相比原生,交互体验上还是有差距。
  2. 体验
    用户在访问网页的时候,在浏览器开始显示之前都会有一个白屏的过程,受限于设备性能和网络速度,白屏会更加明显。为了解决体验问题,微信推出“微信 Web 资源离线存储”,类似 HTML5 的 Application Cache,能解决部分白屏问题,但是web的体验上还是和原生有着很大落差,例如页面的切换,页面加载条等。
  3. 管控
    web页面自由度很高,需要花很大的人力去检查页面是否存在违规等操作。
小程序应运而生

如果有一套Hybrid框架,用客户端原生技术与Web技术结合的混合技术,让开发者可以获取强大的原生能力,类原生体验,而且又在管控之下,那就完美了。
这就是小程序,"界面主要由成熟的 Web 技术渲染,辅之以大量的接口提供丰富的客户端原生能力。同时,每个小程序页面都是用不同的WebView去渲染,这样可以提供更好的交互体验,更贴近原生体验,也避免了单个WebView的任务过于繁重。",官网如是说。

双线程模式主要解决:体验、管控

体验:web页面开发渲染线程和脚本线程是互斥的,长时间的脚本运行可能会导致页面失去响应或者白屏。而双线程模式是不会有这个问题的。而且这个模式下,强制使用了MVVM框架的数据驱动,即让视图状态和视图绑定在一起,同时也使用了虚拟dom优化体验

管控:阻止开发者使用浏览器的开发性接口,通过提供一个沙盒环境来运行开发者的js代码,只能使用微信提供开放的方法来获取元素的一些信息。这样就避免开发者的操作不在管控范围。除了JS用沙盒环境管控,html也改用了封装过的wxml(WeiXin Markup language) ,css改为wxss(WeiXin Style Sheet),为了管控,同时也是为了提供更多功能,例如封装了播放直播的live-player、滚动选择器picker-view。另外,也提供了wxs(WeiXin Script)让wxml在渲染的时候也可以做一些逻辑处理。

怎样做的(how)

小程序是基于WEB规范封装的一套Hybrid框架
  1. 小程序的渲染层和逻辑层是用多个webview实现的,
  2. 逻辑层的JS代码全部载入到一个Webview里面,称之为AppService,整个小程序仅仅有一个,而且整个生命周期常驻内存;
  3. 而全部的视图(wxml和wxss)都是单独的Webview来承载,称之为AppView。

AppService和AppView之间通过Native(系统层)来做中转媒介,如下图:


渲染层和逻辑层的分工:

  1. 渲染层(WXML、WXSS文件)和数据相关。即:怎样表现数据(Show Data)。
  2. 逻辑层(js文件)负责产生、处理数据。即:什么样的数据(What Data)。
  3. 逻辑层(js文件)通过 Page 实例的 setData 方法传递数据到渲染层。即:怎么传递数据(Send Data)。

我们在渲染层的请求并不会直接到了逻辑层,而是会先到了系统层。在系统层先进行操作处理一部分功能再将数据传递给逻辑层,逻辑层也一样。 所以不能频繁进行setdata请求绑定交互。
如果当前数据并不会在页面中进行显示,数据也不应该定义在data中,否则每次在进行数据绑定时,这些数据也会进行一次从数据层到逻辑层的传递,占用了系统层的资源。
而在小程序三大运行环境中,逻辑层和渲染层的实现也是有一些区别的:
另外,由于是Hybrid框架,让开发者能以近似Web的方式开发,并且可以在线更新代码,只是要经过微信审核。
但是原生Native部分的能力是有版本差异的,所以小程序开发者在使用一些新的能力时候需要增加版本控制,这个也是无法避免的一个问题。

逻辑层AppService

可将AppService暂且理解为一个简单的页面,主要功能是负责逻辑处理部分的执行,底层提供一个WAService.js的文件来提供各种api接口(新功能需要做低版本兼容),主要是下面几个部分:

  1. 消息通信封装为WeixinJSBridge
  2. 日志组件Reporter封装
  3. wx对象下面的api方法
  4. 全局的App,Page,getApp,getCurrentPages等全局方法
  5. 对AMD模块规范的实现

整个AppService就是载入一堆JS文件,包括小程序配置config,上面的WAService.js(调试模式下有asdebug.js)。剩下就是我们自己写的全部的js文件,一次性都载入。并且整个包会被缓存在用户本地,使得可以有需要的更新,所以root的手机是有方法获得小程序包的,通过反编译可以获得压缩过的代码。

渲染层AppView

接近Web,只是标签使用小程序提供的一些组件(新组件需要做低版本兼容)。和逻辑层的通讯过程:

  1. 小程序逻辑层调用宿主环境的 setData 方法。
  2. 逻辑层执行 JSON.stringify 将待传输数据转换成字符串并拼接到特定的JS脚本,并通过evaluateJava 执行脚本将数据传输到渲染层。
  3. 渲染层接收到后, WebView JS 线程会对脚本进行编译,将js对象再次转化成真实的Dom结构,交由渲染层线程渲染。得到待更新数据后进入渲染队列等待 WebView 线程空闲时进行页面渲染。
  4. WebView 线程开始执行渲染时,待更新数据会合并到视图层保留的原始 data 数据,并将新数据套用在WXML片段中得到新的虚拟节点树。经过新虚拟节点树与当前节点树的 diff 对比,将最新变化的内容反映到真实的DOM树中,更新UI。同时,将新的节点树替换旧节点树,用于下一次重渲染。

渲染层的组件是通过Exparser框架支持的,内置在小程序基础库中。主要分为两类:

  1. 内置组件:基础的,主要是解决两个问题:"原生交互"(例如button的分享功能)和"容易卡顿"(例如movable-view这种因双线程模型导致手势识别不好实现的组件,因为双线程交互会有一定延时)。
  2. 自定义组件:开发者可以自行扩充的组件Component。开发者可以将常用的节点树结构提取成自定义组件,实现代码复用。当然,纯展示的复用代码建议使用template模板引入的方式实现,因为组件是比较耗费性能的

作者:好嗨饿
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
鲜花
鲜花
鸡蛋
鸡蛋
分享至 : QQ空间
收藏