5b7a4c1e8cc627b88cd0272419456d7c
Android 架构之动态化之路

文末可添加作者微信,加入Android进阶小专栏读者群

2019/08/16 新增JsBridge的权限管控及权限更新策略;
2019/03/12 新增离线包加密机制:通用加密、强加密、硬核加密;

正文

相对于可实时发布上线的Web前端和后端而言,移动端的一大通病就是动态化能力不足。代码的变更必须通过漫长的发布、审核、升级来实现,这对于越来越讲求速度的互联网节奏而言非常不相符。

当前无论是大厂还是小厂,都对于动态化能力都有不同程度的追求。小则动态修复线上问题,大则实时发布最新功能。动态化特性对于业务的推动是非常巨大的。因此,对于动态化技术的掌握也成为了各个开发者的必备技能,面试佳品。

而且现在越来越多人提及大前端,而动态化就是大前端的核心部分。作为开发者不能只会写上层的Js代码,更重要的是了解这些框架背后的实现原理。

当然了,动态化本身涉及面非常广,且有一定技术深度,从最早的PhoneGap,到Atlas、VirtualAPK,再到React Native、Weex、PWA,甚至小程序、Flutter,每项技术在推出时都反响很大,这也体现了大家对动态化技术的欢迎。这其中每个技术框架内部都有非常多可探究的点,本专栏会从其中挑一些依次进行讲解,以求将整体动态化面貌及其内在原理展现给大家。

本文会对于这些动态化方案做一个整体的介绍,同时会针对当前应用最广的Hybrid方案做较为细致的分析。

I. 动态化方案

在动态化的持续发展中,不少大厂都推出了自己的动态化方案。我们可以将这些方案统一分成四大类:

1. H5容器

这种是目前应用最广、接入成本也最低的动态化方案:基于WebView+JsBridge来实现动态化。

WebView是Android和iOS的基础组件,而且随着业务对WebView的依赖不断加重,Google和Apple也在不断对WebView进行优化,比如Android在4.4之后采用了Chromium作为内核。

另外,国内也有大厂对WebView做了深度定制优化,比如微信公众号里用的X5WebView,阿里UC浏览器内核等,针对稳定性、流畅性和安全性都做了深入的优化。

这种方案可以同时发挥H5的动态性和移动端的稳定性,迁移成本非常低,也是目前应用最广的。当然了,这种方案的问题在于性能,H5的性能无论如何是比不过Native的。对于重性能的场景下比如复杂动画,适合用Native开发;但对于重运营的页面,则非常适合Hybrid开发。

本文也会针对这种方案做详细阐述。

2. 虚拟运行环境

第一种方案除了H5开发,还需要Android iOS两端去实现对应的JsBridge,提供相关的JsApi给H5使用。而第二种方案则是追求纯前端开发。

比如React Native和Weex,只需要开发者做基本的配置,就可以只通过Javascript(ReactJs, Vue.js)来实现大部分功能,对于移动端的依赖减到最小,把移动端统一成了一种虚拟运行环境,只要写一份代码,就可以在多个平台上运行。

当然,这种方案的弊端同样在于性能。虚拟环境的背后是繁多的Js与Native通信,对于普通页面还好,但对于大型列表等复杂页面则会出现较为严重的性能瓶颈。

最近新出的Flutter也是类似的解决方案,目前也还在改进中,可以保持一定的关注。

3. 布局动态化

这种方案的思路就是x通过动态下发配置文件,客户端解析并像积木一样,拼接生成对应的视图。这种方式可以通过更改配置文件,实现视图的实时发布。比如天猫的TangramVirtualViewvLayout一套方案,通过下发json生成对应的UI组件,绑定数据,而且性能也还不错。


4. 插件化

插件化是前几年比较火的方案,通过对四大组件的Hook等方案,实现动态下发一些不常用的业务模块实现功能的动态化更新。比如阿里的Atlas,将不同功能模块打包进入对应的bundle,在运行时再逐个加载进来。

不过随着Android生态越来越严格和规范,这种方案已经越来越难通用了。

总体的动态化方案可以参考下图来了解下动态化方案的概貌:

美团客户端动态化实践

美团客户端动态化实践

II. H5容器动态化技术

作为起源最早的H5容器方案,在如今动态化方案百花齐放的时候,仍然非常稳固,这主要源自它的迁移成本低(基于WebView即可)、开发效率高、更新效率高等。比如阿里这种电商型场景,虽然有了各种各样的动态化方案(Weex VirtualView Tangram Atlas),但H5容器方案仍然是其中不可替代的一环。不断迭代的UC Webview为阿里繁多的业务类型提供稳固的内核保障。

下面我们针对H5容器的原理和优化点进行讲解。

WebView增强

对于Android而言,4.4开始改成了Chromium内核,综合指标相对还不错,所以系统WebView是比较常用的。当然,也有很多公司会采用定制WebView。比如支付宝的Nebula容器内部采用了UCWebView
,腾讯微信公众号采用的X5Webview

采用定制WebView的话可以帮开发者屏蔽一些底层差异,提高稳定性(降低Crash率,UCWebView Crash率是系统webview的1/3、X5WebView Crash率低于0.06%)、安全性(比如防劫持、保障网址安全),也能带来更好的性能和速度,节省流量。尤其对于Android系统而言,定制WebView能为我们处理很多兼容性问题,无缝隐藏各种系统差异,这一点非常重要。

对于 X5Webview 还有一个吸引点,就是如果用户手机上安装了微信、手机QQ、手机QQ空间等App,它可以自动做到X5内核共享。

另外,如果遇到WebView方面的问题,也可以和对应的团队进行沟通改进。

目前主流的方案会采用 X5Webview/UCWebView + 系统WebView,后者作为降级兜底方案,以防止前者初始化失败之类问题。


JsBridge实现

JsBridge是Hybrid里非常重要的一环,它将Native的诸多能力暴露给了H5,可以让H5更加强大。不论是这里提到的Hybrid开发,还是React Native,或者今年盛行的小程序,都要依赖JsBridge。

那么,什么是JsBridge呢,它是如何实现的?

我们知道,JsBridge的核心功能就是负责Js与Native的通信,这也就意味着我们首先需要去解析Js代码,然后将它对接到相关的Native函数上(对Android而言就是Java函数),从而实现一次通信。那么谁来解析Js代码呢?

在我们上面提到的WebView或者说是其内部的Chromium、WebKit内核,都包含了一个核心的组件:JavascriptCore(下面简称JsCore),正是它提供了Js运行环境。Java的小伙伴都知道JVM,而JsCore就是类似的角色。

对于React Native、Weex而言,它们内部其实都是依赖了JsCore来解析它们的Js代码,参考Weex 客户端 JavaScript 引擎;而对于Hybrid而言则是直接依赖整个WebView,里面除了JsCore,还有一些Html渲染相关的组件,比如WebCore,这些是RN、Weex所不需要的。

另外,JsCore是一种Js执行引擎,横向来看,我们也可以选用Google的V8引擎、Mozilla 的 SpiderMonkey 引擎等。我们熟悉的Chrome浏览器内部就是采用的 V8 Js引擎

Js调用Native一般有几种方案:

  • addJavascriptInterface 直接添加原生的JsModule进去
  • console.log 拦截onConsoleMessage方法,可能在边缘机型不适用
  • window.prompt 拦截onJsPrompt方法,如果没有拦截可以会弹出奇怪弹框
  • shouldOverrideUrlLoading 拦截url跳转回调,速度较慢

一般使用前两种方案实现,对于只支持4.2以上的,可以考虑第一种方案。

top Created with Sketch.