2016年6月24-25日, GMTC全球移动技术大会 将在北京举行,本届大会,我们邀请了《App研发录》的作者包建强老师,前来分享《Android插件化:从入门到放弃》的内容。这个有趣的标题引起了大家的兴趣,我们就来采访一下包建强老师,看看他为什么会取这个标题,以及对移动应用架构和Android插件化的理解。
包建强:大家好。我是包建强。简单介绍一下我自己,我工作12年了,有8年时间在惠普微软这些软件公司做一线开发,2012年进入互联网,做了4年移动App。去年写了本书,《App研发录》,卖的还不错,感谢大家捧场。我有一个技术博客,坚持写了6年,地址是:http://cnblogs.com/jax。
我是08年微软MVP。这些年来我一直很珍惜这个荣誉,MVP讲的是技术分享的精神,我虽然现在不怎么写技术博客了,但遇到有想法的年轻人,还是会鼓励他们把自己的经验分享出来,至少要给若干年后的自己看。
我目前涉足的领域比较多,前段时间还在区块链折腾,顺手学了点Docker和Go语言,现在对VR很感兴趣,在私下研究Google的SDK。
包建强:当年写《App研发录》这本书时,留下些遗憾,比如说我只讲了Android的框架设计,而没有谈到iOS,其实它们的思想是一致的,但是iOS并不能理解这一点,因为他们大都看不懂Android的代码。此外,iOS有自己的技术体系,比如cocospods,比如runtime,这都不是能和Android放在一本书写清楚的,所以接下来我要写一本给iOS开发人员看的《App研发录》,也就是第二卷。
另一个遗憾就是当时我的Android插件化技术还没有想明白,所以书中就没提到这块技术,其实我是预留了它的位置的,这本书本来是有13章的,但是2015年突然冒出来很多Android插件化的开源框架——我到现在还在怀疑这帮哥们是不是提前约好了这个时间点,然后很多新思想就把我搞晕了,就没敢把写好的那一章放到书中。现在证明这个决定是正确的,时隔半年,我对Android插件化的认识已经发生了很大的变化,已经不是一章几十页就能把这个话题说明白的了,所以接下来《App研发录》的第三卷讲专门讲Android插件化技术。
如果还有第四卷,那就是MobileAPI和推送、IM技术,这都是很远的事情了,我还不敢想。
包建强:无线的技术越来越成熟,已经从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技术界的风向标。
包建强: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崩溃。
当然,上面说的都是我的个人见解,也没有全对全错之说,不要迷信权威,大胆质疑,多做实验,然后再找我讨论,谁对听谁的。
包建强:哈哈哈。我是觉得,如果这个演讲主题是《Android插件化:从入门到精通》的话,就体现不出真是想明白了这个领域。所以最近冒出来各种从入门到放弃、改行、住院、出家的技术书籍,我觉得那反而是说明作者是真的大彻大悟了,武侠小说里面有写,虽“飞花摘叶皆可伤人,草木竹石均可为剑”,就是这种境界。
不过要声明的是,我对Android插件化的认识,远不如冯森林、张勇、罗迪这些人。
我有一个Android插件化研究的群,三十多人,都是国内各个插件化开源项目的作者、公司插件化的实施者,以及传经授道的博客作者。我们都感受到Android插件化技术基本已经成型了,随着React Native的横空出世,Android插件化会慢慢退出历史舞台,也就是这一两年的事情吧,所以要给后人留下点什么,于是便有了这次技术分享。
我的分享讲包括插件化技术的历史和各种八卦,各个技术流派,一些小例子,各个开源项目的思想,插件化实施过程中遇到的问题,以及未来的发展方向。45分钟,我尽量讲的生动有趣一些。
包建强:就像我前面说的,Android插件化技术目前已经基本成熟了,各大公司也都有了自己的插件化平台,机制可能会有不同,因为插件化有很多流派,每个流派的思想都不太一样。
接下来说几点插件化的问题:
首先是这个新功能发布和热修复是两码事,但是我们把这二者都混在插件化中了。这就有问题了。热修复是很轻量级的东西,完全可以使用AndFix或Nuwa来解决,但是我们现在通常是使用发布新的插件来修复线上bug,一两天一个插件化版本,用户会不停的下载升级插件。
其实呢,插件化是用来发布新功能的。一般来说,大版本是一个月一次,中途想上一个功能,这时候才是插件化的最好使用场景。所以说,要把新功能发布和热修复拆开成两套机制,而不要混为一谈。
我再举个例子,就是用插件化来发布新功能。然后我就发现,在下一次发布大版本之前,只有50%的用户升级了插件并使用的是新功能。这是因为Dalvik的机制导致的,一旦加载了这个插件的原始版本,就会一直使用,即使你下载的新版本插件,也只能在App退出进程后重启才能生效。Android用户一般不会杀App的进程,也就我们这些程序员或发烧友才知道要去什么地方杀进程。为了解决这个尴尬的问题,我们曾经试图把App做成多进程的,每个模块的插件都是一个单独的进程,插件升级会自动杀之前插件的进程,然后再启动新的进程来运行新版本的插件。这就是张勇的DroidPlugin的思想,在他的框架出来之前,国内的插件化机制都是单进程的,都有我刚才说的这个问题。然后就有人给出一种解决方案让App崩溃后重启,虽然也能解决问题,但就会产生一种搞笑的场景,用户正在酒店模块下单,这时因为机票模块的插件升级而重启,这是很让人抓狂的事情。
其次,就是代码质量下降。开发人员不再像过去那样『提心吊胆』的写代码,生怕自己的一次疏忽而导致大面积崩溃而对公司生意产生影响。我刚才举的那个例子,一两天就要发一次插件新版本来修复线上bug,就是代码质量下降的表现。
第三,就是四大组件都需要插件化机制吗?我是做那种旅游行业App的,几百个Activity,大都是列表或者详情,然后有几个详情页面可以下单或者用户登录,它们更多的逻辑在于调用服务器API获取数据然后展示给用户。所以类似于电商、旅游、O2O领域的App,把Activity的插件机制搞定就好了。
第四,大家有没有发现,插件化技术只在中国会开花结果,国外的开发人员都在忙什么?大概是老外觉得线上有崩溃或者严重错误,发个新版本让用户更新就是了,不是什么大不了的事情。遇到类似于迅速发布新功能的需求,Facebook会另辟蹊径,发明了React Native,写的是H5但运行的是Native源码,走这个变通的套路,当然也是闷头研究了很久才对外公布的,iOS差不多了,Android还有很大的性能问题还没有解决,但我估计也就今年年底的事了。React Native的稳定,同时意味着插件化的落幕。这就是Android插件化的未来。
包建强:精通这个词,我是真心不敢说的。所谓无知者无畏,我曾经以为自己很牛,尤其是《App研发录》出版后听到一片赞赏的时候,但随着接触到更多的开发人员,听到更先进的思想,看到更牛逼的技术,我发现自己的很多技术落伍了。
比如我在写书的这一年里,因为这本书大部分在讲Android,所以无形中就把iOS的技术拉下了,直到去年下半年看JSPatch的源码时,我才发现对runtime的理解还只是皮毛。再比如说iOS结合Cocoapods进行模块化拆分。
接下来,我介绍一些自己的学习心得。
由InfoQ主办的GMTC全球移动技术大会将于6月24日在北京召开。来自BAT、携程、滴滴、微博、开源社区等等的技术专家联袂分享,主题包括应用架构、性能优化、动态化、插件化、Swift、React Native等,为中高级移动开发工程师献上一场技术盛宴! 6折期最后三天!4月23日截止 ,欲购从速!