最近,帮朋友面试了一个八年工作经验的 Android 开发工程师,面试完我感觉五味杂陈,不知道对方的面试感受如何,这里也不多加揣测了。话不多说,应聘者的大概履历如下:
基本信息
姓名:xxx
年龄:32
性别:男
工作年限:8 年
求职意向:Android高级开发工程师
期望薪资:20k
个人描述:本人有 8 年Android实际开发经验,先后待过 5 家公司,负责过各方面 Android 端项目,涉及电商、iot、直播、社交等领域。有独立解决问题的能力,遇到问题尽量是一个人去解决的,具有较强的学习能力,经常关注和了解新技术。拥有良好的团队协作能力和执行能力,吃苦耐劳,能够保证项目进度的平稳进行和快速迭代。
技术专长
- 熟练掌握 Java,熟悉 Java 虚拟机原理
- 掌握常见的设计模式和数据结构算法
- 掌握Android基础(四大组件、五大布局、多线程等)
- 熟悉Android主流框架(Glide、Retrofit、GreenDao、Logger、Gson等)
- 熟练掌握Android中的 MVP、MVVM 等架构
- 熟悉第三方登录、支付、分享等功能开发
- ......
工作经历
- xxx软件公司(外包) | 一年 | Android 高级开发
负责xxx iot核心模块功能开发,负责xxx部分业务的协同开发,项目性能优化处理等
- xxx软件公司(外包) | 两年 | Android 开发组长
负责多个电商产品的Android端研发,带领Android团队从项目搭建到核心功能开发再到项目最终上线,全程都有参与
- xxx软件公司(外包) | 两年 | Android 开发
略...(类似,无亮点)
- xxx科技公司(创业) | 两年 | Android 开发
负责公司所有android端app的开发工作
- xxx软件公司(外包) | 一年 | Android 开发
负责公司Android应用开发工作
项目经验
- xxx商城项目
负责个人中心、订单、退换货和物流信息等模块的开发;
消息推送功能的实现;
项目的性能优化和打包;
- 其他类似,此处略...
看到这里,你有什么想说的吗?期望薪资20k,你觉得他要多了还是要少了呢?
从工作经历来看,并不是说外包公司不好,只是觉得作为技术人员不能只满足于业务代码的堆叠,虽然对各种业务了然于胸,对职业发展来说也是种宝贵财富,但更重要的不应该是自身的技术能力吗?这才是核心竞争力!我们经常会被问到的一个问题:你觉得你的项目有哪些亮点,可以选取一两个来说一下吗?如果每天纯粹做业务开发,各种 CV 大法而不去思考技术的迭代创新或者可维护性,那么三年和八年的工作经验有什么本质区别吗?我看到最多的借口就是:平时公司任务多,太忙了,没时间去学习。难道是真的没时间吗?还是说每天回去沉浸在游戏、短视频等“纸醉金迷”中无法自拔呢?时间这东西,挤挤还是有的,哪怕是利用每天上下班路上的时间去看一篇技术文章,这对于我们个人来说,也是一种收获。如果真的没时间,那么你有想过跳出这个舒适圈吗?
你可能会说:简历并不能代表一切,有可能他是刚刚准备,还没有来得及完善。好的??,虽然几率很低,但的确也会发生这种情况,那么我们来看看面试的大概过程吧。
PS: ???表示面试官;??♂表示应聘者。
???:先来做个简单的自我介绍吧!
??♂:简历中的内容叙述了一遍,此处略…
???:为什么想来上海发展?
??♂:安逸太久,想改变自己。
???:看你之前开发了这么多项目,有哪个让你收获最大?能不能详细介绍一下你在项目里担任的角色以及收获?
??♂:让我印象最深刻的应该是xxx商城项目,因为之前一般都是我独立去完成整个app的项目开发。这项目里,我主要负责一些核心功能开发,如订单和个人中心,通过这项目,让我个人在团队协作方面有了进一步成长,另外技术框架的封装和使用方面也得到了进一步提升。
???:说到订单功能,你可以说说订单超时的处理思路吗?如果存在多个取消的订单,你会怎么处理?
??♂:只要给每个超时的订单设置一个定时器,时间到了之后就改变订单状态,并刷新列表就可以了。
???:除了给列表中的每个订单设置一个定时器,还有其他实现思路吗?
??♂:暂时想不到了…
???:那么你可以说说这个项目的技术栈组成是什么样子的吗?
??♂:大概是 MVP+Retrofit+Glide+Gson+RxJava+ButterKnife 这种,当然还有自定义View、事件分发机制、动画和异步任务使用等。
???:你可以说一下 Android 中异步任务的实现方式有哪些吗?
??♂:一般是通过 Handler+Thread的形式,也可以使用Runnable,另外还提供了AsyncTask来实现,其他的就记不得了。
???:说到AsyncTask,你有了解过它的源码吗?它的实现原理是怎样的?
??♂:这个不太清楚,没有看过它的源码,但我用过它,知道它里面常见的几个方法,doInBackground用来处理耗时操作,处于异步线程,其他方法在UI线程执行。
???:有听过 HandlerThread 和 IntentService 吗?
??♂:额…好像没有听过
???:那好吧,你可以说一下事件分发机制吗?
??♂:当点击的时候,会先调用顶级 ViewGroup 的 dispatchTouchEvent,如果顶级的 ViewGroup 通过 onInterceptTouchEvent 拦截了此事件,则此事件序列由顶级 ViewGroup 处理。如果顶级 ViewGroup 设置setOnTouchListener,则会回调接口中的 onTouch,此时顶级的 ViewGroup 中的 onTouchEvent 不再回调,如果不设置 setOnTouchListener 则 onTouchEvent 会回调。如果顶级 ViewGroup 设置 setOnClickListener,则会回调接口中的 onClick 方法。如果顶级 ViewGroup 不拦截事件,事件就会向下传递给他的子 View,然后子View(ViewGroup)就会调用它的dispatchTouchEvent方法。
???:(终于能接得上话了)嗯,那么你项目里有处理过滑动冲突的情况吗?如何处理的?
??♂:有处理过 ListView 和 ScrollView 之间的滑动冲突问题,当时应该是通过重写外层ScrollView的onInterceptTouchEvent方法来根据一些特定逻辑判断是否需要拦截。
???:有了解过哪些第三方框架的源码吗?
??♂:额,这个没有看过源码,只是简单知道Retrofit对Okhttp进行了简单封装,Glide用了三级缓存。
???:你知道Activity的启动流程是怎样的吗?
??♂:点击桌面 App 图标,Launcher 进程采用 Binder IPC(具体为ActivityManager.getService 获取 AMS 实例) 向 system_server 的 AMS 发起 startActivity 请求,system_server 进程收到请求后,向 Zygote 进程发送创建进程的请求;Zygote 进程孵化出新的子进程,即 App 进程。App 进程通过 Binder IPC 向 system_server 进程的 AMS 发起 attachApplication 请求,system_server 进程的 AMS 在收到 attachApplication 请求后,做一系列操作后,通知 ApplicationThread bindApplication,然后发送 H.BIND_APPLICATION 消息,主线程收到 H.BIND_APPLICATION 消息,调用 handleBindApplication 处理后做一系列的初始化操作,初始化 Application 等。system_server 进程的 AMS 在 bindApplication 后,会调用 ActivityStackSupervisor.attachApplicationLocked,之后经过一系列操作,在 realStartActivityLocked 方法通过 Binder IPC 向 App 进程发送 scheduleLaunchActivity 请求;App进程的 binder 线程(ApplicationThread)在收到请求后,通过 handler 向主线程发送 LAUNCH_ACTIVITY 消息。主线程收到 message 后经过 handleLaunchActivity,performLaunchActivity 方法,然后通过反射机制创建目标 Activity。
???:嗯好,那么你可以说一下Binder机制吗?
??♂:这个我了解的比较少,只是知道它是C/S结构,是跨进程通信的方式之一。
???:好的,那我们来聊点别的…
??♂:…
???:…
??♂:…
大概面试过程就是这样,后面还问了他一些 Java 基础和多线程,掌握情况不是很好。期间还问了他 synchronized 和 volatile 的区别有哪些,他只回答了三个字:不知道。八年开发,按理来说应该肯定远远不止这个水平,可结果也并不显得差强人意。
另外,从面试者个人项目经验来看,虽然接手过很多项目,而且业务种类也很多,但是并没有吃透其中某一个业务。比如,同样是做电商项目,你有将外面同类知名产品拿来与自己开发的项目进行比较吗?这些产品经历了长时间的市场和用户验证,一定有很多地方是值得学习和思考借鉴的,假如这个功能让你去实现,你有什么思路呢?如何进一步去优化呢?其实我们周围有很多东西值得我们思考和学习,但很多时候我们可能选择了无视。
现在,你觉得给他开多少薪资合适呢?所幸,他当前也已经意识到自己安逸太久,需要突破一下自己了,虽然有些迟,但只要能够努力和自律,相信成长空间也是非常大的。毕竟成事在人,谋事在天。
通过这件事联想到自己最近的裸辞,虽然很多人劝过我不要这么果断,先看看形势,但所幸我做出的应该是正确的决定。如果想要在技术领域站稳脚跟,除了不断汲取新知识,拓宽自己的知识面,更要紧的是挖掘自己的技术深度,这样才不会很容易就被后来人所取代。人不能在一个地方安逸太久,否则,这份安逸会成为束缚自己的泥沼,想挣脱也并非容易了。趁我们还年轻,如果我们心中已作出决定,而苦于时机未成熟、无法实施的时候,倒不如斩断自己的后路,破釜沉舟,背水一战,未尝不可。又或者,待十年之后,你鼓起勇气想破釜沉舟,但是,前方还有多少彼岸任你停靠呢?
本文可能比较枯燥无味,但也点明了一些我们技术人员的现状和挑战 ,找工作不难,难的是找到真正符合我们职业发展规划的那条路。有捷径可以走吗?有!最大的捷径就是早日看清自己的现状,跳出舒适圈,去追求自己真正想要的,并为之奋斗!
对于 Android 开发者来说,要成为优秀的 Android 开发工程师,不只能够让你在工作中更加游刃有余,同样会让你在职业发展中面临更多优质的机遇。而一个初中级 Android 工程师在通往高级甚至是资深工程师的发展过程中,我认为这份Android面试指导手册中超过 90% 的内容都是你必须掌握,且无法绕过的。这些笔记和面试文档已经全部整理收录好了,需要参考学习的可以 点击这里 进行查看。