在Xamarin.Forms中实现包括iOS平台在内的发布后App在线热更新.
这是一个简单的技术可行性验证项目,结论是可用,但是别照着抄,很多东西还需要进一步完善才能用于生产.
如果要在一个App中实现热更新,通常的大方向是:Hybrid App, 简单的说就是在App里插网页, 重定义WebView的一些功能实现网页JavaScript和原生代码的交互。
顺着Hybrid App这条思路我们也做了一些尝试,目前还不尽如人意,尝试的方向是Xamarin + Angular/Vue 和 Xamarin + Blazor (后者非常智障的是它居然依然不支持热更),在这个方向上我们还会继续尝试和优化,暂且不表,这个repo要说的是另一个思路:
我们从游戏领域搬来了一个大宝贝:ILRuntime.
游戏的客户端逻辑复杂度通常远大于传统App,并且游戏是个对性能要求极其严苛的领域。这就导致了,游戏领域要实现热更新,是比传统App要更折腾的。
比如一个明显的区别就是:去tm的Dom,去tm的webview
也就是说,这个repo走了一条与Hybrid App截然相反的道路。
好了不卖关子了,游戏通常是这么处理热更的:从架构层面把程序拆分成两个部分,一个部分叫原生层(有的公司又叫冷更层,在Xamarin里原生层通常指**.Droid, **.iOS这部分,所以为了区分,以下都叫冷更层了),另一个部分叫热更层。
其中框架、基础功能和模块,以及性能要求极高的部分逻辑存放于原生层,而一些与具体业务相关的、对性能要求不苛刻的代码和资源,放在热更层。
在更新时,使用补丁的概念对热更层进行更新。
具体说回我们这个repo本身,照着这个repo的思路往下走的话,也会沿用游戏的思路进行热更新:冷更层决定了App的母包版本,热更层内容的变动通过补丁包的形式针对母包进行打补丁;当冷更层需要变动内容时,则需要重新出母包,更新到App Store等应用商店。(服务端通常应该同时支持多个母包版本.)
(其实上面这堆对于游戏开发者来说基本是废话,请游戏开发者读者忽略上面这堆内容)
铺垫了一堆,实际上在本repo中,热更得以实现的原理说起来非常通俗易懂:
- Xamarin.Forms的XAML文件和C#代码文件,在通过编译器后,都会在DLL里变成IL代码.
- 我们从游戏领域搬来了
ILRuntime
这个大宝贝,它可以在包括iOS在内的运行环境中解释执行IL代码,于是热更新实现了.
这个解释执行的操作,对于我们App的冷更层来说,几乎是无感知的。不过还是有些工作要做:
- 跨域(跨热更工程和冷更工程)的委托调用,需要提前在母包中注册.
- 跨域的子类继承,需要提前在母包中编写适配器
- 涉及到一些反射操作时,冷更层是拿不到热更层的类信息的(因为对于冷更层来说,这个类压根不存在),需要编写CLR重定向代码
- 单纯解释执行慢还有GC,我们可以事先在冷更层中进行一些CLR绑定操作来解决这些问题.
(当然这些在ILRuntime官网文档都有说明,我就是顺便提一句)
嗯,
彩蛋:
我们顺着这条路往下,顺便试了下把游戏里的FairygUI给搬到了Xamarin.Forms上 …… 以后有机会给大家看看