跨端技术谈

Posted FarmGuo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了跨端技术谈相关的知识,希望对你有一定的参考价值。

目前流行的跨端方案按实现形式可分为三种
1,通用WebView
2,React Native
3,Flutter

1.通用WebView

ios端,WebView当前是WKWebView,拥有独立的Content进程渲染和Networking进程请求。性能比UIWebView高效、稳定。通常使用JSContext进行JS和OC的交互(JSPatch),或者使用WKWebView来进行JS和OC的交互(Hybrid)。
JSPatch原理:
1,构建环境,先利用JSContext生成一个交互环境,里面定义了JS调用OC的方法,如_OC_defineClass、_OC_callI、_OC_callC。然后将JSPatch.js进行代码注入,这个文件代码定义了后续Patch执行的环境,如defineClass函数和Object原型链上的__c函数等等。其余.js的文件是要执行的代码,准确说是以defineClass开头的字符串,但字符串里面混合了JS的代码。以defineClass开头,后面的参数是类名(需要hook或增加实现的类名)、对象方法和类方法。而后2个参数是以字典的形式做参数的,字典的key就是方法名,value就是具体的实现(JS语言形式)。在注入前,会修正下格式,将.alloc()的格式修改为.__c(“alloc”)(),对应之前在Object原型链上定义的__c函数。这样注入的时候就调用到了defineClass函数。
2,hook,defineClass函数中,调用Native的_OC_defineClass方法,传入对象方法和类方法。_OC_defineClass指向了defineClass函数。在里面会根据类和方法进行hook,替换原来的实现,具体而言就是:1.将原SEL指向
msg_forward,使得调用SEL走消息转发流程。2.将forwardInvocation的实现替换为自定义的JPForwardInvocation。3.以ORIG开头的SEL保存着原实现。4.将新的实现(JS中定义的,此时是JSValue)保存到到全局的_JSOverideMethods字典中,这个字典是2级字典,一级key为类名,二级key为方法名。5.在类中添加JP_开头SEL的实现,这个实现是一个中转者,会调用callWithArguments来执行新的实现(JS中定义的)。

Hybrid原理
以WebViewjavascript为例,WebViewJavascriptBridgeBase的messageHandlers属性是个字典,保存了JS到OC的回调,key是方法名,value则是block。

在WKWebView初始化加载完成后JS会新建一个iframe,并设置其style.display设置为none,并添加到当前document上。并将这个ifrme的src设置为“bridge_loaded”,decidePolicyForNavigationAction就会收到这个跳转,根据URL的类型通过evaluateJavaScript进行代码注入,注入的JS代码中定义了_handleMessageFromObjC、_fetchQueue、_doSend、callHandler等函数。然后生成了一个新的iframe并保存到名为messagingIframe的全局变量,然后将其style.display设置为none,并添加到当前document上。
Native调用JS的方法,都是通过evaluateJavascript,传入JS代码来实现的。而Hybrid中的调用也是如此,在Native的_dispatchMessage方法中,使用evaluateJavascript调用_handleMessageFromObjC函数,会将参数转换为字符串,里面包含了callbackId和其他数据。JS中根据callbackId来执行具体的调用。
JS要调用Native时,先调用_doSend,里面准备好数据如方法名、参数、方法执行完后的回调,保存到sendMessageQueue中,然后将messagingIframe这个iframe的src置为“queue_message”,decidePolicyForNavigationAction会收到这个跳转,根据URL的类型,调用WKFlushMessageQueue方法,这个方法让WebView执行_fetchQueue()函数,其会返回之前准备的数据(字符串形式)。然后调用flushMessageQueue,其会将之前准备的数据转换为字符串后返回,WKFlushMessageQueue获取执行后的结果,调用flushMessageQueue,在里面将字符串转为字典,取出方法名和参数。通常情况下JS要调用Native后还需要一个回调,来获取执行的结果。在字典中取出callbackId,生成一个临时Block,当作参数传给messageHandlers中的Block。Native的方法执行完成后,会调用这个临时Block并传入执行结果,这个临时的block里面,会拼一个字典,responseId对应callbackId,responseData对应执行后返回的结果。然后调用_dispatchMessage。JS方根据responseId来执行具体的回调。

2.React Native

在iOS端,使用JavaScriptCore引擎进行前端和OC Native进行交互,将前端的语言实现转换为端内的代码(RC开头的类)来进行实现,最终使用Native的渲染,渲染性能比通用WebView好些。由于中间多了一个转换的过程,对性能会有一定的影响。而且涉及到前端到Native的代码转换,当Native版本升级时,需要适配改动。

3.Flutter

新的前端语言Dart,生成Widget Tree,Element Tree,Object Renders
底层使用Skia渲染框架。

以上是关于跨端技术谈的主要内容,如果未能解决你的问题,请参考以下文章

浅谈基于Web的跨平台桌面应用开发

凹凸技术揭秘 · Taro · 从跨端到开放式跨端跨框架

跨端技术一出,客户端真要灭亡了吗?

跨端技术一出,客户端真要灭亡了吗?

前端开发:如何正确地跨端?

美团跨端一体化富文本管理技术实践