专访包建强:为什么我说 Android 插件化从入门到放弃?

  • 徐川

2016 年 4 月 20 日

话题:移动Android语言 & 开发架构

2016 年 6 月 24-25 日,GMTC 全球移动技术大会将在北京举行,本届大会,我们邀请了《App 研发录》的作者包建强老师,前来分享《Android 插件化:从入门到放弃》的内容。这个有趣的标题引起了大家的兴趣,我们就来采访一下包建强老师,看看他为什么会取这个标题,以及对移动应用架构和 Android 插件化的理解。

InfoQ:请您介绍一下自己,目前主要关注哪些技术领域?

包建强:大家好。我是包建强。简单介绍一下我自己,我工作 12 年了,有 8 年时间在惠普微软这些软件公司做一线开发,2012 年进入互联网,做了 4 年移动 App。去年写了本书,《App 研发录》,卖的还不错,感谢大家捧场。我有一个技术博客,坚持写了 6 年,地址是:http://cnblogs.com/jax。

我是 08 年微软 MVP。这些年来我一直很珍惜这个荣誉,MVP 讲的是技术分享的精神,我虽然现在不怎么写技术博客了,但遇到有想法的年轻人,还是会鼓励他们把自己的经验分享出来,至少要给若干年后的自己看。

我目前涉足的领域比较多,前段时间还在区块链折腾,顺手学了点 Docker 和 Go 语言,现在对 VR 很感兴趣,在私下研究 Google 的 SDK。

InfoQ:据说您要续写《App 研发录》,能介绍一下接下来会写什么内容吗?

包建强:当年写《App 研发录》这本书时,留下些遗憾,比如说我只讲了 Android 的框架设计,而没有谈到 iOS,其实它们的思想是一致的,但是 iOS 并不能理解这一点,因为他们大都看不懂 Android 的代码。此外,iOS 有自己的技术体系,比如 cocospods,比如 runtime,这都不是能和 Android 放在一本书写清楚的,所以接下来我要写一本给 iOS 开发人员看的《App 研发录》,也就是第二卷。

另一个遗憾就是当时我的 Android 插件化技术还没有想明白,所以书中就没提到这块技术,其实我是预留了它的位置的,这本书本来是有 13 章的,但是 2015 年突然冒出来很多 Android 插件化的开源框架——我到现在还在怀疑这帮哥们是不是提前约好了这个时间点,然后很多新思想就把我搞晕了,就没敢把写好的那一章放到书中。现在证明这个决定是正确的,时隔半年,我对 Android 插件化的认识已经发生了很大的变化,已经不是一章几十页就能把这个话题说明白的了,所以接下来《App 研发录》的第三卷讲专门讲 Android 插件化技术。

如果还有第四卷,那就是 MobileAPI 和推送、IM 技术,这都是很远的事情了,我还不敢想。

InfoQ:移动应用架构在过去几年取得了很大的发展,您对此有什么看法?App 架构还有发展的空间吗?

包建强:无线的技术越来越成熟,已经从 12 年时的一片荒芜,发展为现在的蔚然大观。对于国人来说,我们比较关注的是这么几个点,热修复,性能,开发效率,App 体积,数据驱动产品。这些点目前都已经有了很好的解决方案。这个话题很大,我就不展开说了。

我 04 年刚出来工作的时候,IT 行业正在从 CS 转型为 BS。CS 就是客户端 - 服务器,04 年之前大都是这样的软件,后来互联网的技术成熟起来了,就开始把原先的系统都搬到网站上,这就是 BS,全称是 Browser-Server。

后来 BS 做的多了,大家觉得 BS 太单薄,很多功能不支持,不如 CS,于是就搞出个 SmartClient 的概念,也就是智能客户端,Outlook 就是一个很好的例子,你可以脱机读和写邮件,没网络也可以,什么时候有网络了,再发写好的邮件发出去。

再后来 Flash 就火起来了,这个本来是网页制作工具三剑客,却阴差阳错的成为了网页富客户端的鼻祖。于是便有了 Flex,微软这时候也来插一脚,搞出个 Silverlight。与此同时,JavaScript 也在发力,并逐渐取代前者,成为富客户端的最后赢家,那时候有本书非常火,叫做《JavaScript 设计模式》。

前面铺垫了那么多,就是想说明 App 也在走同样的发展道路,先沉淀几年,把网站的很多技术都搬过来,也就是目前的发展情况,差不多该有的也都有了,下一个阶段就是从 CS 过渡到 BS,Hybird 技术就是上面说到的 BS,但是有很多缺陷,尤其是 WebBrowser 性能很差,然后便出现了 React Native,我们可以理解为富客户端。再往前发展是什么样我不知道,但是这个发展周期是很清晰的。大家赶快盯紧了 Facebook 的开源项目,这哥们经常放大招儿,已俨然成为 App 技术界的风向标。

InfoQ:您曾经说过 iOS 领域的架构和 Android 与 WP 相比有些距离,您现在也这么认为吗?能否具体解释一下?

包建强:Android 和 iOS 领域的很多思想,都是来自于 WP。我有幸在这 3 个平台上都做过 App。我是微软出身,所以做 C# 有将近十年的经验,而 WP 是基于 C# 和 Silverlight 的,所以我做 WP 是轻车熟路。比较可惜的是,WP 中的技术和思想都是很好的,只是这个产品比不过 Android 和 iOS,所以现在做移动的已经没有多少人提它了,但是要知道,现在 Android 和 iOS 比较火的几个技术和思想,都是从 WP 搬过来的。我举几个例子:比如说 MVVM,这个思想最早就是微软提出来的。微软有一门技术叫 Silverlight,用来取代 Flash 的,它是借助于一种叫做 XAML 的 XML 语言,来绘制 UI。Android 和 iOS 现在最火的 MVVM 和 MVP,都是来源于此。

在 iOS 开发里,很多同学还在纠结 Model 该有哪些代码,ViewModel 该有哪些代码,其实这个问题 8 年前我们就已经讨论清楚了,结论是代码是死的,人是活的,开发团队定一个标准,然后大家遵守执行,这就够了。

再比如说 iOS 使用 Xib 还是手写代码。大家之所以有这个争论,其实是 Xcode 设计的原因。我用过 Xcode、Eclipse、Android Studio 还有微软的 Visual Studio,我认为 Visual Studio 是最好的 IDE 编辑器,没有之一。毕竟这是微软投入了巨大人力来做的一个产品。Xcode 对 Xib 的支持很差,就是点一下啥都没改,但是 git 立刻就显示这个文件被修改了,此外,Xib 中冗余的标签太多,可读性很差,这就导致了从 iPhone 火起来,程序员们就都选择手写 UI,然后一传十、十传百,尤其是培训学校也这么教,就变成了业界标准。但是你看 WP 和 Android,它们都是基于 XML 来绘制 UI 的,WP 和 Android 的开发人员都已经习惯使用 XML 绘制 UI,你让他们手写 UI,他们会觉得很难。

由此而提到 Xcode 另一个反人类的设计,就是在 Xib 和后台代码直接通过连线来生成事件方法,微软的 VisualStudio 从 02 年就在 ASP.NET 支持这个功能,但十几年下来结论是,培养了一群只会拖控件的程序员,他们不知道拖控件背后的原理,以至于对 ASP.NET 的生命周期不清楚,写出很多性能很糟糕的程序。由此及彼,Xcode 其实也是这个问题,那根线会很难维护,尤其是连线很多的时候,这时候,在程序里为控件绑定事件反而是更好的选择。

最后说到 WP 的墓碑机制。在 App 切到后台时,会把当前状态记下来,再切回到前台时,之前的状态会被从记录中读取,从而恢复到之前的状态,这被称为墓碑机制。这个机制是借助于 WP 对数据绑定的支持,因为我把数据也就是 Model 实体与 UI 绑定了,所以我只要保存 Model 实体对象,以后就可以还原到之前的状态。

Android 和 iOS 就缺少这样的机制,主要是数据绑定做的不如 WP 灵活,导致了 App 因为内存不足而回收后台应用占用的内存时(iOS 叫内存报警,Android 叫内存回收),再把被回收内容的 App 切回到前台时,这时候一些变量或者 view 为空就崩溃了。你们看过 Android SDK 的贪食者游戏源码吗?里面是通过保存贪食者的坐标,从而用户在旋转屏幕销毁 UI 后还能回到游戏最后的状态。页面中有 1-2 个变量还好办,如果有几十个变量需要保存状态,就体现出 WP 墓碑机制的好处了。目前 Android 和 ios 的解决方案是重新走一遍当前页面的初始化过程,让用户重新操作一遍刚才填写的流程,尽量不让 App 崩溃。

当然,上面说的都是我的个人见解,也没有全对全错之说,不要迷信权威,大胆质疑,多做实验,然后再找我讨论,谁对听谁的。

InfoQ:您在 GMTC 中的议题叫做《Android 插件化:从入门到放弃》,请问这个标题代表什么意思?

包建强:哈哈哈。我是觉得,如果这个演讲主题是《Android 插件化:从入门到精通》的话,就体现不出真是想明白了这个领域。所以最近冒出来各种从入门到放弃、改行、住院、出家的技术书籍,我觉得那反而是说明作者是真的大彻大悟了,武侠小说里面有写,虽 “ 飞花摘叶皆可伤人,草木竹石均可为剑 ”,就是这种境界。

不过要声明的是,我对 Android 插件化的认识,远不如冯森林、张勇、罗迪这些人。

我有一个 Android 插件化研究的群,三十多人,都是国内各个插件化开源项目的作者、公司插件化的实施者,以及传经授道的博客作者。我们都感受到 Android 插件化技术基本已经成型了,随着 React Native 的横空出世,Android 插件化会慢慢退出历史舞台,也就是这一两年的事情吧,所以要给后人留下点什么,于是便有了这次技术分享。

我的分享讲包括插件化技术的历史和各种八卦,各个技术流派,一些小例子,各个开源项目的思想,插件化实施过程中遇到的问题,以及未来的发展方向。45 分钟,我尽量讲的生动有趣一些。

InfoQ:您对 Android 插件化的发展有什么看法?

包建强:就像我前面说的,Android 插件化技术目前已经基本成熟了,各大公司也都有了自己的插件化平台,机制可能会有不同,因为插件化有很多流派,每个流派的思想都不太一样。

接下来说几点插件化的问题:

首先是这个新功能发布和热修复是两码事,但是我们把这二者都混在插件化中了。这就有问题了。热修复是很轻量级的东西,完全可以使用 AndFix 或 Nuwa 来解决,但是我们现在通常是使用发布新的插件来修复线上 bug,一两天一个插件化版本,用户会不停的下载升级插件。

其实呢,插件化是用来发布新功能的。一般来说,大版本是一个月一次,中途想上一个功能,这时候才是插件化的最好使用场景。所以说,要把新功能发布和热修复拆开成两套机制,而不要混为一谈。

我再举个例子,就是用插件化来发布新功能。然后我就发现,在下一次发布大版本之前,只有 50% 的用户升级了插件并使用的是新功能。这是因为 Dalvik 的机制导致的,一旦加载了这个插件的原始版本,就会一直使用,即使你下载的新版本插件,也只能在 App 退出进程后重启才能生效。Android 用户一般不会杀 App 的进程,也就我们这些程序员或发烧友才知道要去什么地方杀进程。为了解决这个尴尬的问题,我们曾经试图把 App 做成多进程的,每个模块的插件都是一个单独的进程,插件升级会自动杀之前插件的进程,然后再启动新的进程来运行新版本的插件。这就是张勇的 DroidPlugin 的思想,在他的框架出来之前,国内的插件化机制都是单进程的,都有我刚才说的这个问题。然后就有人给出一种解决方案让 App 崩溃后重启,虽然也能解决问题,但就会产生一种搞笑的场景,用户正在酒店模块下单,这时因为机票模块的插件升级而重启,这是很让人抓狂的事情。

其次,就是代码质量下降。开发人员不再像过去那样『提心吊胆』的写代码,生怕自己的一次疏忽而导致大面积崩溃而对公司生意产生影响。我刚才举的那个例子,一两天就要发一次插件新版本来修复线上 bug,就是代码质量下降的表现。

第三,就是四大组件都需要插件化机制吗?我是做那种旅游行业 App 的,几百个 Activity,大都是列表或者详情,然后有几个详情页面可以下单或者用户登录,它们更多的逻辑在于调用服务器 API 获取数据然后展示给用户。所以类似于电商、旅游、O2O 领域的 App,把 Activity 的插件机制搞定就好了。

  • Service 这个组件,大都用于在线音乐的 App,因为后台也要能播放音乐。此外,不管是哪款 App,只要涉及到聊天,都需要 Service 插件来帮忙修改 App 图标上的未读消息数。
  • Broadcast 和 ContentProvider 什么时候使用?像手机助手、安全卫士这类的 App 会着重依赖于这些技术,所以你会看到 DroidPlugin 必须要实现这两个组件的插件化技术,因为作者是在 360 这家公司,而任玉刚的开源框架(目前途牛在使用),以及携程的框架,他们只支持了 Activity 和 Service 就够了,因为大多数电商 App 有这两个就够了。

第四,大家有没有发现,插件化技术只在中国会开花结果,国外的开发人员都在忙什么?大概是老外觉得线上有崩溃或者严重错误,发个新版本让用户更新就是了,不是什么大不了的事情。遇到类似于迅速发布新功能的需求,Facebook 会另辟蹊径,发明了 React Native,写的是 H5 但运行的是 Native 源码,走这个变通的套路,当然也是闷头研究了很久才对外公布的,iOS 差不多了,Android 还有很大的性能问题还没有解决,但我估计也就今年年底的事了。React Native 的稳定,同时意味着插件化的落幕。这就是 Android 插件化的未来。

InfoQ:您精通 Android、iOS、WP 三个平台的应用开发,请问您是如何学习的?对于初学者有什么建议?

包建强:精通这个词,我是真心不敢说的。所谓无知者无畏,我曾经以为自己很牛,尤其是《App 研发录》出版后听到一片赞赏的时候,但随着接触到更多的开发人员,听到更先进的思想,看到更牛逼的技术,我发现自己的很多技术落伍了。

比如我在写书的这一年里,因为这本书大部分在讲 Android,所以无形中就把 iOS 的技术拉下了,直到去年下半年看 JSPatch 的源码时,我才发现对 runtime 的理解还只是皮毛。再比如说 iOS 结合 Cocoapods 进行模块化拆分。

接下来,我介绍一些自己的学习心得。

  • 首先就是去写代码。有一个做 Android 的哥们升级为架构师,需要了解 iOS 这门技术,来问我怎么能迅速精通 iOS,我就告诉他,别玩虚的,脚踏实地跟着 iOS 开发团队做几个需求,半年之后再来谈这个话题。Android 和 iOS 的很多现金思想可以相互借鉴,我建议做一门技术的同学,也适当学习另一门技术。
  • 咬着牙看开源项目。比如说 JSPatch,怎么看?我有个建议,你看 JSPatch 的版本提交历史,从第一次提交看起,这时候的功能应该是最简单的,也是最容易看懂的,然后看历史每次提交都修改了哪些东西,你能搞清楚作者的思路是什么。
  • Android 插件化虽然有被 React Native 取代的势头,但还是要搞清楚插件化所涉及的各种思想和技术。我这一年来的心得是,这是提高自身内功的极好办法。尤其是涉及到 Android 系统底层的各种 Hook。
  • 写技术博客吧。每天看文章只能是看过,一个月后能沉淀下来的没有多少,好记性不如烂笔头。一开始你可以转载或罗列精品文章的链接,慢慢的开始分享自己的心得,翻译些技术文章,技术水平提高是一个循序渐进的过程。

由 InfoQ 主办的 GMTC 全球移动技术大会将于 6 月 24 日在北京召开。来自 BAT、携程、滴滴、微博、开源社区等等的技术专家联袂分享,主题包括应用架构、性能优化、动态化、插件化、Swift、React Native 等,为中高级移动开发工程师献上一场技术盛宴!6 折期最后三天!4 月 23 日截止,欲购从速!

移动Android语言 & 开发架构