2018 之后,Android 工程师将何去何从?

本文探讨了Android开发领域的现状及未来趋势,指出虽然初级职位竞争激烈,但高级人才仍供不应求。文章列举了一系列必学、选学及推荐学习的技术,并强调了技术的实际应用场景才是关键。

Android 工程师真的烂大街了么?

Google I/O 的 Session ,有相当一部分是围绕 Android 展开的, 移动互联网是互联网的里程碑,而手机是 Google 数百种设备中最重要的, Google 一直以来都在优化 Android 的用户体验。虽然移动开发这两年已经接近饱和,但只要仔细观察就不难发现,是初级工程师的门槛在变高,而各个大厂的高级/专家级工程师/架构师缺口仍然很大。


Android 技术每年在变化,不知道学哪些技术?


这个问题每个人的答案都不一样,我在这里从另外一个角度来说。

首先问你们一个问题,为什么想做 Android 移动开发?

  • 因为 Android 简单好学吗?不, Android 并不简单也不好学。

  • 因为 Android 开发轻松吗?不, Android 开发直接面对的是用户,细节的体验要求更高。

  • 因为 Android 开发(互联网行业)薪水高?不见得吧,各行各业都有做得好的,即便是在互联网行业,移动开发的待遇未必在工程师中出于领先状态。

这个问题我也一直在思考,回想自己是怎么走上 Android 这条路的,和今天在现场看 Google I/O 的感受是一样的,一个词: cool 。

Google 通过技术改变世界,改善人们的生活,给人类更大的可能性,作为大生态中的一份子,贡献出自己的一份力量,以后老了才不会后悔。

好,我们先不谈梦想,做技术是因为它好玩有趣,所写即所得,而移动开发最接近终端用户,你的一两行代码,说不定就在什么时候,引起用户的尖叫:“ OMG! Amazing! so cool~ ”

说到这里,结论就很明显了,我们要学习的技术,是能够带给用户愉悦体验的,是能够符合 Google 的愿景 make good things 的,是让用户更加 wellbeing 的。

也就是说,让 App 的体验更好,更流畅、更稳定、功能更强大,所有能达到这些目的的技术,都要学,学了不是为了不被淘汰,而是为这个世界多贡献一份力。尽管生活中会遇到各种各样负能量的琐事,但工作是为了创造价值,不开心的烦恼少去想才不枉人间走一遭。


哪些技术必学,哪些技术选学,哪些技术推荐学?


先说必学


  • Java 基础知识

  • Android 基础知识(这个不掌握就不要谈其他东西了)

  • 网络基础知识(不联网的 app ,除了单机游戏外估计找不到什么好应用了)

  • 图片基础知识(图片加载库得熟悉吧)

  • 媒体播放基础知识(如 exoplayer )

  • Firebase ( I/O 持续优化的东西,不学说不过去了,况且还有 FCM )

  • Kotlin (大势所趋,没什么好说的,不学肯定后悔)

  • Support 包(搞向下兼容必须用到的东西)

  • 构建系统(包括 gradle maven proguard 等等)

  • 测试框架(包括今天 Google 推的 mockito )

  • ReactiveX (重点是流的概念,而不是异步)

  • Json 序列化和反序列化

  • 组件化

  • Material Design

  • 相机基础知识

  • 二维码基础知识

  • 定位基础知识

  • 自动化脚本(如 python )

  • 数据库基础知识

  • 加解密基础知识


再说选学,选学的意思是用到了就学,没用到不学也没关系


  • 热补丁技术

  • React Native

  • 插件化

  • NDK 开发

  • 直播技术

  • 媒体播放高级知识(编解码相关)

  • VR 技术

  • Flutter 框架(目前主要做 UI 的)

  • Android 架构框架

  • Android Things


最后说推荐学的


  • AR 技术(作为技术我一直认为这块是移动产品的蓝海,谁发现了场景的新大陆,谁就拿下了 onepiece )

  • AI 技术( TensorFlow )

  • 指纹技术


不要为了学而学,多想想用在什么场景


任何技术不用在实际的业务场景中,就没有价值,和学生时代被老师要求背书一样。

作为移动开发工程师,多想想如何才能让用户更加愉悦,那就少不了自己要多用,所以 Google 可以招到这么多优秀的工程师加入,这些工程师每天每天(刻意重复)都不断地使用自己的产品,时间久了就会有终端用户的代入感,才能设身处地为用户考虑。如果你都不把自己当成是产品的目标用户,可能一个起码的自测都会忽视掉。

很庆幸能够加入一家像 Google 一样每个员工都把产品用心打磨,不断使用不断练习的公司,这样终有一天一个能被称为愿景的东西才有可能实现吧。

### 二叉树遍历结束后的执行流程与返回位置分析 在讨论二叉树遍历时,无论是前序、中序还是后序遍历,都涉及递归调用栈的行为。以下是对二叉树遍历结束后函数执行流程和返回位置的详细说明。 #### 执行流程概述 当完成对某一子树的遍历后,控制流会按照递归调用栈逐步回退到上一层级。具体来说: - 每次递归进入一个新的节点时,都会将其压入系统的调用栈。 - 当某个节点及其左右子树均被处理完毕后,当前递归层的任务即告终结,此时从调用栈弹出该层对应的上下文,并继续执行上一层未完成的部分[^1]。 #### 返回位置解析 对于任意给定的递归遍历算法(以前序为例),其典型实现如下所示: ```c void preorderTraversal(BiTree T) { if (T != NULL) { visit(T); // 访问根节点 preorderTraversal(T->lchild); // 遍历左子树 preorderTraversal(T->rchild); // 遍历右子树 } } ``` 在此过程中,“返回位置”的概念可分解为以下几个方面: 1. **基础条件判断**:如果遇到空节点,则直接跳过对该分支的操作并退出当前层次的递归; 2. **访问顺序遵循定义**:依据不同类型的遍历模式调整三个主要动作之间的相对次序; 3. **最终回归起点**:一旦整棵树的所有节点都被依次访问过后,最外层初始调用也将随之终止,标志着整个过程正式完结[^2]。 值得注意的是,在实际运行期间,每当某一分支下的所有子孙均已妥善处置之后,程序便会自动回到父辈所在的高度重新评估剩余部分直至全局范围内的每一项皆已纳入考量范畴为止[^3]。 --- ### 示例代码展示完整生命周期 为了更加直观地理解这一机制,我们可以通过增加打印语句的方式观察每一步的状态变化情况: ```c #include <stdio.h> #include <stdlib.h> typedef struct BiTNode { char data; struct BiTNode *lchild, *rchild; } BiTNode, *BiTree; // 假设visit操作只是简单输出节点值 void visit(char c){ printf("%c ", c); } void preorderTraversal(BiTree T) { if (T != NULL) { printf("Visiting Node (%c)\n", T->data); visit(T->data); printf("Entering Left Child of (%c)\n", T->data); preorderTraversal(T->lchild); printf("Leaving Left Child of (%c)\n", T->data); printf("Entering Right Child of (%c)\n", T->data); preorderTraversal(T->rchild); printf("Leaving Right Child of (%c), Returning to Parent.\n", T->data); } else { printf("Encountered Null Pointer, Exiting Current Recursion Level.\n"); } } int main(){ // 构造一个简单的二叉树 A / \ B C /\ D E BiTree root = malloc(sizeof(struct BiTNode)); root->data='A'; root->lchild=malloc(sizeof(struct BiTNode)); root->rchild=malloc(sizeof(struct BiTNode)); root->lchild->data='B'; root->lchild->lchild=NULL; root->lchild->rchild=NULL; root->rchild->data='C'; root->rchild->lchild=malloc(sizeof(struct BiTNode)); root->rchild->rchild=malloc(sizeof(struct BiTNode)); root->rchild->lchild->data='D'; root->rchild->lchild->lchild=NULL; root->rchild->lchild->rchild=NULL; root->rchild->rchild->data='E'; root->rchild->rchild->lchild=NULL; root->rchild->rchild->rchild=NULL; preorderTraversal(root); return 0; } ``` 上述代码不仅实现了标准意义上的先序遍历功能,还额外加入了辅助性的日志记录以便追踪内部运作细节。 --- ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值