AboutFE icon indicating copy to clipboard operation
AboutFE copied to clipboard

32、各个跨端方案的比较、跨端的问题答疑

Open CodingMeUp opened this issue 5 years ago • 8 comments

http://www.52im.net/thread-1870-1-1.html http://www.52im.net/thread-2641-1-1.html

Flutter

avatar

  1. Flutter 在各个原生的平台中,使用自己的 C++的引擎渲染界面,没有使用 webview,也不像 RN、NativeScript 一样使用系统的组件。简单来说平台只是给 Flutter 提供一个画布。
  2. 界面使用 Dart 语言开发,貌似唯一支持 JIT,和 AOT 模式的强类型语言。
  3. 写法非常的现代,声明式,组件化,Composition > inheritance,响应式……就是现在前端流行的这一套
  4. 一套代码搞定所有平台, 端的一致性。

Flutter 为什么快?Flutter 相比 RN 的优势在哪里?

  1. Skia 引擎,软件层渲染,RN底下是原生的,有可能使用OPENGL硬件层渲染,Chrome, Chrome OS,Android,Firefox,Firefox OS 都以此作为渲染引擎。
  2. Dart 语言可以 AOT 编译成 ARM Code,让布局以及业务代码运行的最快,而且 Dart 的 GC 针对 Flutter 频繁销毁创建 Widget 做了专门的优化。
  3. CSS 的子集 Flex like 的布局方式,保留强大表现能力的同时,也保留了性能。
  4. Flutter 业务书写的 Widget 在渲染之前 diff 转化成 Render Object,对,就像 React 中的 Virtual DOM,以此来确保开发体验和性能。
  5. RN 使用 JavaScript 来运行业务代码,然后 JS Bridge 的方式调用平台相关组件,性能比有损失,甚至平台不同 js 引擎都不一样。
  6. RN 使用平台组件,行为一致性会有打折,或者说,开发者需要处理更多平台相关的问题

闲鱼 flutter 和 rn 性能测试 https://www.yuque.com/xytech/flutter/gs3pnk

CodingMeUp avatar Dec 31 '19 12:12 CodingMeUp

Q: 小程序诞生的背景,小程序架构是什么样的,性能为什么好,微信小程序,支付宝小程序有什么区别

1:诞生背景: 早在微信小程序之前,有力推轻应用的百度,有来自 HTML5 中国产业联盟的 DCloud 所主张的流应用,小程序不是一天发展起来的,07年H5和iPhone同年立项,H5推翻了IE+Flash,却没有达到承载优秀的移动互联网体验的地步, iPhone站稳脚跟后跟上APP STORE的开发,安卓也异军突起,于是:在移动互联网初期,应用生态被定了基调 —— 原生开发。在那个时候,硬件不行,也没有其他办法,原生开发才能在低配硬件上带来商用体验。但大家都在怀念 H5,那种无需安装更新、即点即用,直达二级页面的动态发布。 国内有一批做浏览器的厂商,尝试去改进 HTML5,他们提出了轻应用的概念。通过给 WebView 扩展原生能力,补充 JS API,让 HTML5 应用可以实现更多功能。不过这类业务没有取得成功,HTML5 的问题不止是功能不足,性能体验是它更严重的问题。

微信的 JS SDK,为它的浏览器内核扩充了大量 JS API,砍掉较多复杂的初始化损耗,定制化,让开发者可以用 JS 调用微信支付、扫码等众多 HTML5 做不到的功能。(但是引用了后仍旧 存留首页白屏载入问题),于是需结合Hybrid应用 Client/Server模式和HTML5的动态性(流应用概念:把之前 Hybrid 应用里的运行于客户端的 JS 代码,先打包发布到服务器,制定流式加载协议,手机端引擎动态下载这些 JS 代码到本地,并且为了第一次加载速度更快,实现了应用的边下载边运行), 后来这套应用号模式 就改为 小程序。

模式 (技术标准 -> 基础平台 -> 开发工具 -> 培训市场 -> 框架诞生 -> 周边生态逐步完善 -> 轮子之上的轮子)

2: 架构

  • 不选RN的原因
  1. RN 所支持的样式是 CSS 的子集,会满足不了 Web 开发者日渐增长的需求,而对 RN 的改造具有不小的成本和风险。
  2. RN 现有能力下还存在的一些不稳定问题,比如性能、Bug等。RN 是把渲染工作全都交由客户端原生渲染,实际上一些简单的界面元素使用 Web 技术渲染完全能胜任,并且非常稳定。
  3. RN 存在一些不可预期的因素,比如之前出现的许可协议问题
  • 渲染和逻辑 (纯web,复杂交互因为UI渲染和JS线程在同一个线程,造成抢占式性能损耗) (纯Native,由于字节码问题动态发布不好保证) (取长补短, 于是采用介于客户端原生技术与 Web 技术之间的,互相结合各自特点的技术来渲染)

从渲染底层来看,PhoneGap与微信 JS-SDK 是类似的,它们最终都还是使用浏览器内核来渲染界面。而 RN 则不同,虽然是用 Web 相关技术来编写,同样是利用了 JavaScript 解释执行的特性,但 RN 在渲染底层是用客户端原生渲染的。选择类似微信 JSSDK 这样的 Hybrid 技术,即界面主要由成熟的 Web 技术渲染,辅之以大量的接口提供丰富的客户端原生能力。同时,每个小程序页面都是用不同的WebView去渲染,如复杂的地图视频,同层渲染,这样可以提供更好的交互体验,更贴近原生体验,也避免了单个WebView的任务过于繁重。在原生则是往 WebView 的 window 对象注入一个原生方法,最终会封装成 WeiXinJSBridge 这样一个兼容(胶水)层,主要提供了调用(invoke)和监听(on)这两种方法。开发者插入一个原生组件,一般而言,组件运行的时候被插入到 DOM 树中,会调用客户端接口,通知客户端在哪个位置渲染一块原生界面。在后续开发者更新组件属性时,同样地,也会调用客户端提供的更新接口来更新原生界面的某些部分。

JS SDK,小程序双线程部分 渲染和逻辑分离,单纯的JS执行环境, 通过对于其中的控件也进行了自定义。因此完全采用这个沙箱环境不能有任何浏览器相关接口,只提供纯JavaScript 的解释执行环境,多 WebView 的架构, 每一个小程序页面都是不同的WebView 渲染后显示的(所以serviceWorker这种就不适用), 在iOS下是用内置的 JavaScriptCore框架,在安卓则是用腾讯x5内核提供的JsCore环境, 我们可以创建一个单独的线程去执行 JavaScript,在这个环境下执行的都是有关小程序业务逻辑的代码(逻辑层 - JS 脚本),而界面渲染相关的任务全都在WebView线程里执行,通过逻辑层代码去控制渲染哪些界面(渲染层 - WXML 模板->JS对象和 WXSS 样式)

  • 通信 小程序是基于双线程模型,那就意味着任何数据传递都是线程间的通信,也就是都会有一定的延时。这不像传统Web那样,当界面需要更新时,通过调用更新接口UI就会同步地渲染出来。在小程序架构里,这一切都会变成异步。 异步会使得各部分的运行时序变得复杂一些。比如在渲染首屏的时候,逻辑层与渲染层会同时开始初始化工作,但是渲染层需要有逻辑层的数据才能把界面渲染出来,如果渲染层初始化工作较快完成,就要等逻辑层的指令才能进行下一步工作。因此逻辑层与渲染层需要有一定的机制保证时序正确,通过Json的方式进行数据的传递,提高性能的方式就是减少交互的数据量,和RN比通信成本小,只是在Native过了一层不需要和native渲染太多通信。

  • 缓存 不同小程序的本地缓存空间是分开的,每个小程序的缓存空间上限为10MB,如果当前缓存已经达到10MB,再通过wx.setStorage写入缓存会触发fail回调。还针对用户进行缓存,保证隐私问题

  1. 支付宝小程序不同点
  • 可配,支付宝小程序不仅提供 JavaScript+Webview 的方式,还提供 JavaScript+Native 的方式,在对性能要求较高的场景,可以选择 Native 的渲染模式,给用户更好的体验

  • 支付宝小程序虚拟机隔离(通常的做法是在 WebView 里面运行 render 的代码,然后另起一个线程运行 serviceworker,当 serviceworker 需要更新 dom 的时候把事件和数据通过 messagechannel 发送给 render 线程来执行,当业务需要传递到 render 层数据量较大,对象较复杂时,交互的性能就会比较差,因此针对这种情况支付宝提出一个优化的解决方案。该方案将原始的 JS 虚拟机实例 (即 Isolate) 重新设计成了两个部分:Global Runtime 存放共享的装置和数据,全局一个实例 和 Local Runtime 存放实例自身相关的模块和私有数据,这些不会被共享, setData 对象的会直接创建在 Shared Heap 里面,因此 render 层的 Local Runtime 可以直接读到该对象,并且用于 render 层的渲染,减少了对象的序列化和网络传输,极大的提升了启动性能和渲染性能。)

  • 支付宝采用的是 UC 提供的浏览器内核,UC 的同学在浏览器内核的性能、稳定性和兼容性上做了大量的工作,比系统提供的 webview 提升了不少。(稳定性:crash 率只有系统 webview 的三分之一到五分之一;兼容性:不存在各种系统 webview 上的兼容性问题;性能:针对内核启动逻辑,v8 引擎 codecache 深度优化,使得 js 代码解析和编译的时间减少 40% 左右;工具:提供了丰富的工具保障 UC 内核的稳定性和性能)

  • 支付宝更考虑兼容性,微信政务的都大部分在公众号上 小程序偏少

[小程序比较](https://zhaomenghuan.js.org/blog/what-is-emp.html

lllang avatar Jul 10 '20 02:07 lllang

RN 启动和渲染流程,有哪些问题,如何优化,和 weex 有什么区别

重构即将完成!2020版React Native会有多大改善

  1. 用户点击App的图标
  2. UIManager线程:加载所有的Native库和Native组件比如 Text、Button、Image等
  3. 告诉Js线程,Native部分准备好了,Js侧开始加载main.bundle.js,这里面包含了所有的js和react逻辑以及组件。
  4. Js侧通过Bridge发送一条JSON消息到Native侧,告诉Native怎么创建UI。值得一提的是:所有经过Bridge的通信都是异步的,并且是打包发送的。这是为了避免阻塞UI
  5. Shadow线程最先拿到消息,然后创建UI树
  6. 它使用Yoga布局引擎去获取所有基于flex样式的布局,并且转化成Native的布局,宽、高、间距等。
  7. UIManager执行一些操作并且像这样在屏幕上展示UI

当前架构的缺点是:

  1. 有两个不同的领域:JS和Native,他们彼此之间并不能真正互相感知,并且也不能共享相同的内存。
  2. 它们之间的通信是基于Bridge的异步通信。但是这也意味着,并不能保证数据100%并及时地到达另一侧。组件和 API 太过依赖 JSBridge 的初始化,而且通讯能力也局限于这一条通道。
  3. 传输大数据非常慢,因为内存不能共享,所有在js和native之间传输的数据都是一次新的复制, 使用桥接器可以连接JS线程和原生线程,在后台,C++模块围绕一个异步队列messageQuene构建。每当它从任一方获取数据时,都会将数据序列化为字符串并将其通过队列传递,并在到达时反序列化。这意味着所有线程都依赖于跨网桥传输的异步JSON消息,并且这些消息发送到任一端,期望它们在将来的某个时间引发响应,但它还存在拥塞的风险。
  4. 同样,布局设计需要经过很多次才能在屏幕上显示,因为在原生设计布局之前,它需要想尽办法到达Yoga引擎,当然这也意味着要通过桥接器, 无法同步更新UI。比方说有个FlatList,当我滑动的时候会加载大量的数据。在某些边界场景,当有用户界面交互,但数据还没有返回,屏幕可能会发生闪烁。
  5. RN代码仓库太大了。导致库更重,开源社区贡献代码或发布修复也更慢。

新架构优化

RN 在 0.59 版本使用 JSI 取代了先前的 JSBridge 0.60.2 以上的版本, fb 推出了新一代JavaScript执行引擎Hermes 采用JS标准,只需enableHermes Hermes 即可缩短启动时间、减少内存使用量并缩小应用程序大小,专门针对在 Android 上运行优化。

JSI是架起 JS 和Native之间的桥梁,通过在C++层实现一个 JSI::HostObject,现在不需要序列化成JSON并双向传递等一系列操作,实现了Native和 JS间的直接同步通讯, 通过使用JSI,Fabric将UI操作作为函数公开给JavaScript,新的Shadow Tree(决定在屏幕上真正显示的内容)在两个领域之间共享,允许两端直接交互。它抹平了 JavaScript 引擎的差异。使用 JSI,我们不必关心底层是Hermes 引擎还是 JavaScriptCore 引擎,JSI 底层都消化了。因此只需要基于 JSI 的接口编写即可

使用新架构,App启动的流程是这样的。

  1. 用户点击App的图标
  2. Fabric加载Native侧(没有Native组件, Turbo Modules 懒加载)
  3. 然后通知JS线程Native侧准备好了,JS侧会加载所有的main.bundle.js,里面包含了所有的js和react逻辑+组件
  4. JS通过一个Native函数的引用(JSI API导出的)调用到Fabric,同时Shadow Node创建一个和以前一样的UI树。
  5. Yoga执行布局计算,把基于Flexbox的布局转化成终端的布局。
  6. Fabric执行操作并且显示UI

为了完成整个流程,我们几乎做了同样的事情,

  • 但是没有了Bridge,现在我们可以有更好的性能,我们可以用同步的方式进行操作,甚至可以对UI上的同步操作进行优先级排序。启动时间也将更快,App也将更小。
  • JSC引擎与其他(可能更高性能的)JavaScript引擎互换,例如V8。
  • 这种新架构还可以直接控制原生模块。这意味着我们可以在需要时使用原生模块,而不是在启动时将它们全部引导一次。这大大提高了性能,节省了启动时间

滑动白屏问题

  • 原来: 因为 JSBridge 的异步关系导致了 shadow 层最终呈现到原生的 UI 是异步的,而且滑动太快后会有大量的 UI 事件会阻塞在 JSBridge

新架构后

  • 初始化:JS 到 Shadow 层已经是同步操作了,而 shadow 层到原生 UI 变成了可以异步也可以同步操作了,组件可以根据自己的业务场景来适配不同的操作。
  • 滑动过程:原生端直接控制 JS 层渲染,同时创建 shadow 层的 node 节点,node 节点会采用同步的方式渲染原生 UI,整个过程中滑动的渲染是采用的同步操作,所以不会出现旧架构下白屏的问题

weex 最大的优势可以在不支持某些组件的情况下降级成h5渲染【手淘】

lllang avatar Jul 10 '20 02:07 lllang

webview 的内核有哪些,webview 有哪些问题,如何优化,jsBridge 怎么实现,怎么优化

  • 内核 iOS 不允许有第三方内核,iOS2~7:UIWebView;iOS8:WKWebView Andorid 每个版本都自带了浏览器内核,要么是chromium要么是很老的webkit。而微信是自己带的一个改造版的chromium(Blink X5, 同理支付宝UC内核也是,我们也可以自己去外网拉内核过来做修改)。苹果是用的自己的新版webkit

  • 问题。可讲小程序纯web渲染的缺点,优化围绕小程序趋势,跨端趋势

  • 优化(白屏到秒开,做离线化,提前找时机如天猫游戏等预加载,去远程拉取资源打到容器内)

jsBridge

JavaScript 调用 Native 推荐使用 注入 API 的方式,Native 调用 JavaScript 则直接执行拼接好的 JavaScript 代码即可,最终演化为一个 BridgeName 对应一个 Native 功能或者一类 Native 消息 (对于接受消息&&回调):用一个自增的唯一 id,来标识并存储回调函数,并把此 id 以参数形式传递给 Native,而 Native 也以此 id 作为回溯的标识。这样,即可实现 Callback 回调逻辑。

https://github.com/CodingMeUp/AboutFE/issues/32#issuecomment-633236106,

  • jsbridge优化点
    1. 通信(是 Native 和非 Native 之间的桥梁,它的核心是 构建 Native 和非 Native 间消息通信的通道,而且是 双向通信的通道。存在单线程阻塞问题,安卓可用智能代理,通信时候可返回信号值,如游戏是native实时来调,电商就有Webview页面调用)
    2. 注入时期(防止恶意攻击,有注入安全机制,如低版本 频率太快,就会认定为攻击,或者在某段时间内,线程不让出,死锁状态也没法注入,IOS 安卓都是99%注入成功,)

lllang avatar Jul 10 '20 02:07 lllang

跨端怎么跨,思路,实现

从前端两大职责,UI 和 交互逻辑来讲 也可以说从上往下讲,需要 跨端 DSL,跨端组件,跨端容器(容器 api),跨端渲染引擎

  1. 跨端 DSL 很好理解,就是自建一套 DSL 用来做视图层的描述,这套 DSL 最后还是生成 ast
  2. 跨端组件,比如 h5 的 div ,小程序的 View,native 的 View
  3. 跨端 api 比如 h5 的 fetch,小程序的 request,native 的 httpClient
  4. 跨端渲染引擎,比如 flutter 就自建了渲染引擎用来适配不同端是比较彻底的跨端渲染引擎,像 RN 其实还是用的各个端自己的渲染引擎,只是把部分 html 和 css 的规范实现了,比如用 yoga 来跨端实现部分 css,这种算是加了一层适配层来实现跨端的渲染
  5. 其实还有跨端的交互逻辑,这个比较无解,几乎所有的端都是另开线程去执行 js,然后和不同端去通信。除了 flutter 是自己用 dart 去做逻辑,底层事件手势全都自己接管了。

以上所有的点都可以从实现方式的好处和缺点,有哪些性能问题,社区都如何解决来了解

eg: flutter的渲染引擎是?

Flutter是由Google推出的开源的高性能跨平台框架,一个2D渲染引擎。在Flutter中,Widget是Flutter用户界面的基本构成单元,可以说一切皆Widget。 它通过自绘 UI ,解决了之前 RN 和 weex 方案难以解决的多端一致性问题。Dart AOT 和精减的渲染管线,相对与 JavaScript 和 webview 的组合,具备更高的性能体验。

渲染流水线

其中 1-6 在收到系统 vsync 信号后,在 UI 线程中执行,主要是涉及在 Dart framework 中 Widget/Element/RenderObject 三颗树的生成以及承载绘制指令的 LayerTree 的创建,7-8 在 GPU 线程中执行,主要涉及光栅化合成上屏。 1-4跟渲染没有直接关系,主要就是管理UI组件生命周期,页面结构以及Flex layout等相关实现,本文不作深入分析。 5-8为渲染相关流程,其中5-6在UI线程中执行,产物为包含了渲染指令的Layer tree,在Dart层生成,可以认为是整个渲染流程的前半部,属于生产者角色。 7-8把dart层生成的Layer Tree,通过window透传到Flutter engine的C++代码中,通过flow模块来实现光栅化并合成输出。可以认为是整个渲染流程的后半部,属于消费者角色

  • Framework层 纯 Dart实现的 SDK,类似于 React在 JavaScript中的作用。它实现了一套基础库, 用于处理动画、绘图和手势。并且基于绘图封装了一套 UI组件库,然后根据 Material 和Cupertino两种视觉风格区分开来。
  • Engine层 纯 C++实现的 SDK,其中包括 Skia引擎、Dart运行时、文字排版引擎等。它是 Dart的一个运行时,它可以以 JIT 或者 AOT的模式运行 Dart代码。这个运行时还控制着 VSync信号(显示器每秒发出60次绘图的信号)的传递、GPU数据的填充等,并且还负责把客户端的事件传递到运行时中的代码。

从上图可知Flutter Engine中的一些绘图原理,Flutter渲染UI的本质就是在VSync信号中快速构建并提供抽象的视图结构数据,所以Flutter的精髓在Flutter Dart Framework里,这里涉及了很多优秀的设计思想、优化策略

eg: flutter 的线程模型

从渲染引擎的视角来看,Flutter 的四个线程的职责如下:

  • Platform 线程:负责提供Native窗口,作为GPU渲染的目标。接受平台的VSync信号并发送到UI线程,驱动渲染管线运行。
  • UI 线程:负责UI组件管理,维护3颗树,Dart VM管理,UI渲染指令生成。同时负责把承载渲染指令的LayerTree提交给GPU线程去光栅化。
  • GPU线程:通过flow模块完成光栅化,并调用底层渲染API(opengl/vulkan/meta),合成并输出到屏幕。
  • IO 线程:包括若干worker线程会去请求图片资源并完成图片解码,之后在 IO 线程中生成纹理并上传 GPU ,由于通过和 GPU 线程共享 EGL Context,在 GPU 线程中可以直接使用 IO 线程上传的纹理,通过并行化,提高渲染的性能

https://www.zhihu.com/search?type=content&q=flutter%E6%B8%B2%E6%9F%93%E5%BC%95%E6%93%8E

eg: 在Android和IOS双端快速去构建一个差异化高效的渲染链路。目前双端主要以web作为跨平台渲染的主要形式下,提供了一个更容易定制和优化的方案

基于Flutter engine,我们去除了原生的dart引擎,引入js引擎,用C++重写了Flutter Framework中的rendering,painting以及widget的核心逻辑,继续向上封装基础组件,实现cssom以及C++版的响应式框架,对外提供统一的JS Binding API,再向上对接小程序的DSL,供小程序业务方使用。对于性能要求比较高的小程序,可以选择使用这条链路进行渲染

受限于小程序worker/render的架构,互动业务中频繁的绘制操作需要经过序列化/反序列化并把消息从worker发送到render去执行渲染命令。基于flutter engine,我们提供了一套独立的2d渲染引擎,引入canvas的渲染管线,提供标准的canvas API供业务直接在worker线程中使用,缩短渲染链路,提高性能。目前已经支持了相关的互动业务在线上运行,性能和稳定性表现很好

lllang avatar Jul 10 '20 02:07 lllang

跨端的发展历史

先聊前端,前端是干嘛的 “前”是指离用户最近,“端”是指端侧。前端就是离用户最近,需要在用户端里实现产品需求并且能给用户尽可能好的用户体验

为什么要跨端,用户可能从很多不同的入口进来,我们无法强制用户端,就只能尽可能在所有端里面满足用户的需求,给用户尽可能好的体验,准确的说“中心和跨端是沉淀出来的,而不是规划出来的,像中台一样,每个企业的IT系统应该根据自己的业务价值沉淀符合业务需要的共享服务中心

  1. pc 时代的跨浏览器兼容
  2. 无线时代的 webview 支持
  3. rn,weex 的出现
  4. 小程序, PWA
  5. flutter

在以上的阶段,都可以从背景,问题,解决方案,遗留或者无法解决的问题来聊

lllang avatar Jul 10 '20 02:07 lllang

RN跨端路由的改造

  1. 原来在一个native view上叠 多层前端页面(为啥要前端自己做路由 1,拓展生命周期, 2那时候没有比较好的路由库) 性能问题 底下如果有地图
  2. 改为 1个页面 native生成一个rctView来做,提高体验 ,并且可支持跳转native页面,后续可配合拆包 和 发布平台 做动态下发
  3. 改造的同时 类似水印这种复杂情况生成就下沉到 native去渲染 就不需要每个react页面去生成一个

RN link 原理

1, 去执行rnpm 且 Rnpm是写在SDK 的 package.json里 2, 就是把native的东西放到native目录底下

RN 通信

  1. JS和OC的通信

“普通的JS-OC通信实际上很简单,OC向JS传信息有现成的接口,像webview提供的-stringByEvaluatingJavaScriptFromString方法可以直接在当前context上执行一段JS脚本,并且可以获取执行后的返回值,这个返回值就相当于JS向OC传递信息。React Native也是以此为基础,通过各种手段,实现了在OC定义一个模块方法,JS可以直接调用这个模块方法并还可以无缝衔接回调。”

    “JS函数调用转ModuleID/MethodID -> callback转CallbackID -> OC根据ID拿到方法 -> 处理参数 -> 调用OC方法 -> 回调CallbackID -> JS通过CallbackID拿到callback执行”
  1. JS和Java的通信

传统的JS 调用 Java方法(Jsbridge、onprompt、log 及 addjavascriptinterface等)RN 中并没有采用,而是借助 MessageQueue 及模块配置表,将调用转化为{moduleID, methodID,callbackID,args},处理端在模块配置表里查找注册的模块与方法并调用, RCTDeviceEventEmitter的emit方法是一个虚方法, 实际是被动态代理了。最终执行者是 JavaScriptModuleInvocationHandler 的 invoke方法里的PendingJSFunction对象的jniCallJS()

在调用条件上,OC/JAVA在调用JS是可以通过JS暴露的接口,在使用模块配置表转化后直接调用的,而JS调用OC/JAVA则是通过事件触发。

https://www.jianshu.com/p/5b5854187aa2

CodingMeUp avatar Jul 13 '20 12:07 CodingMeUp

RN的回调以及线程模型小结

回调

  1. JS 与 Native 间传递的是 callbackID;
  2. callback 参数只能位于方法参数列表的最后面并且最多只能有2个;
  3. RN 通过 callbackID 二进制的最后一位是0还是1,确定是 success 还是 fail;
  4. 由于 JS callback function 无法直接传递给 Native,Native 侧会生成一个 block。

三个线程

  1. JS Thread【JS Thread 是 JS 执行以及 JS 与 Native 通信线程。 简单讲,Native 在此线程执行 JS 代码,JS 调用 Native 接口也发生在此线程上。 JS Thread 的初始化发生在RCTCxxBridge#start方法中】

  2. Native Module Thread【JS 在调用 Native 方法时,Native 方法这个线程上执行】

  3. UI Manager Thread(Shadow Thread) 【UI Manager Thread,UI 组件(UI module)接口执行线程,是一个高优先级的串行队列。 UI 不在主线程, RN 为了提高效率(如: 帧率),会先在UI Manager Thread做一些预处理操作(如计算 frame),最终在渲染上屏时会切到 main thread】

所有 JS 代码都会在独立线程 JSThread 上执行; 可通过 methodQueue 方法自定义 Native module 执行线程; 为了提高效率,所有 UI 组件都会在 UI Manager thread 上预处理,再在 main thread 上渲染上屏。

CodingMeUp avatar Jul 13 '20 16:07 CodingMeUp

rax 相关 http://rax.alibaba-inc.com/

https://fed.taobao.org/blog/taofed/do71ct/why-rax/?spm=ata.13261165.0.0.4b0460d04Tjqkc

https://zhuanlan.zhihu.com/p/100198414

CodingMeUp avatar Jul 16 '20 07:07 CodingMeUp