工作已经四个月了,趁着假期时间,做一个对这四个月的简单总结以及对未来一段时间的规划。回想去年这个时候的我,认为编程是自己最热爱的事情,成为工作后也会同样如此,事实是即便是爱好,成为全职工作后也会变了味,会有定期的需求、不符合设计规范的代码逻辑、与产品或者设计battle以及维护💩山代码.....
对客户端岗位认知的改变§
目前客户端开发岗位分为三大类,Android、iOS以及跨端开发;在2015年之前,一家互联网公司如果想要让自己的业务体验上不降级且高效运行在Android与iOS设备上,需要同时雇佣两批iOS工程师与Android工程师开发同一款应用程序;而在2015年之后ReactNative与Flutter等跨端框架的出现改变了这一格局,开发者不再需要为某一款系统去特地构建应用程序,甚至于React Native在百度百科上的词条是使你能够在Javascript和React的基础上获得完全一致的开发体验,构建世界一流的原生APP。虽然在一开始它们都很不成熟,时过境迁,如今的跨平台方案已经发展到让人叹为观止,在社区以及大公司的技术沉淀下,涌现了无数的优质的方案。
在工作前我一直无法接受跨平台开发这类技术,认为其性能上不及原生,编码体验被原生暴打以及在一些特殊场景下很难使用跨端方案去实现。然而我办理入职后的当天,领完自己的电脑后,接到的第一个任务就是学习公司自研的一套跨端框架Hummer🤡,并且在后来的工作中持续去使用这款框架去做业务需求,同时成为了这款框架的Contributors之一....
如今客户端岗位相比以前,根据公司的业务需求已经分成了两大流派:
- 面向业务序列:例如打车、点外卖这类业务需求,用户发出订单后,就无需将应用一直保持在前台;在此业务背景之下的app,大多会使用跨平台框架去构建,没有使用性能和使用体验这方面的担忧。
- 面向技术序列:例如短视频、即时通讯类的应用程序,意味着用户会持续将应用保持在前台,要时刻保持高性能运行,这些应用大多数使用原生开发,即便是有使用跨平台方案也是在一些极少数的场景下,或者一些不常用的功能上。
跨平台在未来多数的场景之下都会是未来,不计其数的公司会因为开发人员成本使用跨平台方案去开发公司的业务,对于未来的客户端从业人员来说,学习跨平台架构基本上成为了硬性要求;跨平台的市场优势不在于性能或学习成本,甚至平台适配会更耗费时间,但是它最终能让代码逻辑(特别是业务逻辑),无缝的复用在各个平台上,降低了重复代码的维护成本,保证了各平台间的统一性。
跨平台方案对比§
这里说的跨平台方案不包含uniapp、小程序等前端类方案
| 类型 | React Native | Flutter |
|---|---|---|
| 语言 | JavaScript | Dart |
| 环境 | JSCore | Flutter Engine |
| 发布时间 | 2015 | 2017 |
| 代码产物 | JS Bundle 文件 | 二进制文件 |
| 维护者 | ||
| 支持 | Android、IOS、(PC) | Android、IOS、(Web/PC) |
| 使用代表 | 京东、携程、腾讯课堂 | 闲鱼、美团B端 |
实现原理§
在Android和iOS上,默认情况下ReactNative与Flutter都需要一个原生平台的容器(Activity/ViewController)支持,且在原生层都属于一个“单页面应用”,它们之前最大的不同点其实在于UI构建:
React Native§
初学者肯定特别好奇,我写的每一段布局,每一行样式是如何被渲染到移动终端段,其实渲染过程和WebView渲染H5的过程有一些类似,且最终调用的是手机底层的OpenGL ES做渲染,不过WebView是采用的WebKit Core来解析和绘制你写的.

看完React.js的渲染过程就很容易去理解ReactNative,是从Render部分开始产生了分歧,之前的生命周期都是一样的,最大的差别是Render中使用的View不同,所以ReactNative可以理解是React.js在Native伤的一种表现。

ReactNative默认情况下会在Activity下加载JsBundle,然后运行在JavaScriptCore中解析Bundle文件布局,最终通过C++反射堆叠出一系列的原生控件进行渲染。如
如今,ReactNative这类跨端框架已经诞生了无数衍生版本,通过JsBundle存储UI信息以及交互逻辑,最终通过JsCore/QuickJs反射到Native方法来构建原生UI,通过Bridge去拓展其功能及组件。
Flutter§
如果说React Native是为开发者做了平台兼容,那Flutter则更像是为开发者屏蔽平台的概念。
Flutter 中只需平台提供一个 Surface 和一个 Canvas ,剩下的 Flutter 说:“我已经是一个成熟的跨端框架了,我可以自己构建UI”。

Flutter 中绝大部分的 Widget 都与平台无关, 开发者基于Framework开发App,而Framework运行在Engine之上,由Engine进行适配和跨平台支持。这个跨平台的支持过程,其实就是将Flutter UI中的 Widget “数据化” ,然后通过Engine上的Skia直接绘制到屏幕上 。
从以上可以看出:React Native的Learn once, write anywhere的思路,就是只要你会 React ,那么你可以用写React的方式,再去开发一个性能不错的App;而Flutter则是让你忘掉平台,专注于Flutter UI就好了。
DOM§
开发者所熟知的DOM一般都是在接触React所获悉的,这是React的性能保证之一,而在Flutter其实也存在类似的DOM概念。
Widget在渲染时会经过Element变化, 最后转化为RenderObject再进行绘制,而最终组成的RenderObject树才是 “真正的渲染 DOM” ,每次Widget树触发的改变,并不一定会导致RenderObject树的完全更新。
所以在实现原理上React Native和Flutter是完全不同的思路,虽然都有类似“虚拟 DOM 的概念” ,但是React Native带有较强的平台关联性,而Flutter UI的平台关联性十分薄弱。
关于大厂代码§
Q: 设计模式在日常业务开发中的存在感
A: 经常在网络上看到,很多人晒自己碰到的祖传代码,不符合设计规范,只考虑业务逻辑,这种情况在大厂代码中也时常出现,特别是出现在年久失修的代码中,这跟公司成立时间久,经过几年的快速发展扩张,业务体积不断增大,也有一定的关系。
就拿我所接触到的业务代码中遇到的一个问题,有一块数据透传机制采用了Map来做数据容器而不是JSONObject,原因是公司主端的基础代码早在2015年前就已存在,在那个时间点也没有gson这样的解析库,于是只能通过Map来透传数据,而业务线不断扩张的过程中,为了其他业务的稳定性,不能擅作更改于是就有了如今这样的局面。
Q: 为什么在开发流程中没有做到遵守设计模式
A: 在极端条件下,例如Java,设计模式面临着更多的class文件以及更多的代码,在类加载和内存使用的成本上,自然是略微高于不使用设计模式,但是不能一概而论,有些设计模式就是为了提高性能或节约资源成本而出现的。
以及大多数情况下,良好的代码维护性要远远大雨这点性能开销。抛开团队成员的编码水平与人员流动性不谈,在公司中做业务,每一段时间都会有定量的ddl,以及甘特图来统计每个人的业务量,项目快速迭代阶段,时间成本就直接导致了开发流程中很难遵守设计模式。
过去的四个月里我做了什么§
- 学习了React的基础语法与Hummer/Tenon框架的基本逻辑结构,及滴滴出行Android的代码逻辑
- 参与了某项目从0开始到落地 (虽然一直没能上架..)
- 参与了Hummer的开发维护,通读了JNI部分的源码
未来一段时间的计划§
- 新的章节「事无巨细」来详述代码设计,以及源码解读
- 独立app上线计划(计划年后iOS/Android双平台上线)