Android 工程师面试:你离大厂offer还差一份临时磨枪的面试指南和简历优化!

就要到了传统的“金三银四”换作的峰期,在互联网寒冬下,抓住机会就显得尤为重要,特别是现在移动开发已经严重饱和的情况下。那作为 Android 工程师的我们应该从哪些方面去准备呢?例如,不太熟悉的技能要不要写在简历上、要复习哪些 Android 组件的知识、刷算法题⽬有没有⽤,可能在面试前你都会仔细考虑这些问题。 下面我就结合我自身的经验和理解,帮你梳理一下关于简历、面试和算法结构需要准备的内容,分享一些我的心得体会,让你在寒冬下也能拿到大厂的Offer(ps:本文不会过多的讲解Android面试题,而是从宏观的角度分析Android面试的一些软技能还有一些面试应该具备的知识点)。

简历

简历在面试过程会起到至关重要的作用,因此我们需要常常注意简历的撰写。在面试的过程中,面试官通常会经常关注你简历中的工作经历、项目介绍、技能特点这三部分的内容,如果你面试的公司没有固定题目的话,那很多问题都会围绕你简历的这三部分内容去问。因此我们的简历一定要做到简明扼要,并做到有深度有广度。 同时,需要注意的重点是相关技能的书写,首先你要让面试官明确你面试的定级是什么,然后有准备的进行优化。很多时候一个职位对应了很多个职级,在投简历的时候,你的简历需要让面试官给你一个比较明确的定级,否则面试过程会比较被动,也会影响面试官对你的判断。因此这部分的内容需要突出⾃⼰的特点,也要写一些现在公司相对关性的问题,而如你对插件化、热修复、组件化、性能优化等很熟悉,就可以明确的写上,但如果不是很熟悉那么尽量不要去写。

除此之外,项目部分也是简历至关重要的组成部分,这部分内容一定要突出公司的贡献和项目的难点。很多同学可能在公司一直做需求的开发,会觉得公司的项目经验没有亮点,难度也没有那么大,会觉得在这部分内容上比较吃亏。其实,每个需求开发你肯定会对这个需求有一个⾃⼰的设计,在这个过程中你会考虑如何对现有代码的影响最小,如何快捷清晰的实现功能,这些都可以作为项目介绍的内容,然后考虑一下如何把你的这些设计和思考体现在简历上,同样也是个不错的说明。

除此之外,你还可以写一些平时的学习和分享经验,比如开源了个什么库,博客记录平时开发的一些心得体会,这些都会成为你面试的加分项。

面试

对于 Android 工程师来说,面试开始的时候都会问一些Java、Android 的基础知识和算法。针对 Java 的基础知识,我建议你看一下《码出⾼效:Java 开发⼿册》、《深入理解Java 虚拟机》和《Java 并发编程的艺术》这三本书。对于 Android 面试题,很多都是跟系统原理有关的内容,但也有很多没有准确答案的问题,比如四大组件的原理这样的题目,需要你从一个宏观的⻆度去解释一下四大组件,或者你也可以拆分开,然后一个个去讲解。

同时,在面试前你需要提前准备一下,调整一下心态,避免回答问题的时候没有条理,导致面试官对你的逻辑思维能力和语言表达能力产生不好的判断。在Android面试中,经常会问题一些 Android 基本概念,对应这些基本概念一定要理解清楚,比如 Handler.postDelay 的机制、触摸事件机制、自定义 View、如何计算 View ⼤⼩、容器控件如何对⼦控件进行布局、数据库基本操作、Binder 机制、LMK 机制等。

如果你用到一些开源框架,那么面试官也可能会问一些开源框架的原理,我建议你也要多了解一些优秀的网络框架、图片加载框架、日志记录框架、EventBus、AAC 框架的原理。对于相对复杂的插件化和热修复来说,热修复可以去看一下《深入探索 Android 热修复》这本书,插件化可以去看下《Android插件化原理解析》这个系列的文章。

最后,就是性能优化相关的内容,涉及的内容也比较多,最近几年公司对性能优化关注很多,有的同学可能做过专门的性能优化或者⾃⼰开发过一些⼯具总结过一些方法论,这样比较好答⼀些。但是一部分同学可能平时都在关注业务需求开发,性能优化的实战可能并不是很多。我建议你可以从业务开发过程中找一些点来说,比如在做一些公共的业务组件时需要在启动时初始化,那么就需要注意初始化过程中的性能;又或者在做一个列表⻚⾯的时候,在复杂的列表 View 下如何保证滑动性能。相信你在平时开发过程中都会有⾃⼰的考,可以结合具体的情景讲出来。

一般基础面试过之后,面试官会从项目经验,问一些关于项目开发的内容,所以你需要在面试之前针对你之前开发过得项目做详细的准备。比如面试官会让你介绍一下你的项目,你需要体现出这个项目的难点、你在项目中的贡献、项目的具体实 现等,有可能还会问到一些具体的细节,所以建议是实事求是去讲,但一定要对项目的模块非常清晰。除了技术面试以外,有时还有可能会考察一些软技能,比如面试官会考察你跨部门协作能力、沟通能力、时间管理、任务分配和职业规划等。

面试和考试一样,更多的还是要靠平时的积累和临场的发挥,因此不定时的总结是很重要的,因为很多内容不经常使用的话过一段时间之后就会忘掉,这样就会出现原本已经做过的东西,因为忘记了细节,结果在面试过程中没法很好地展现出来。就比如插件化、热修复这样的技术,其实原理相对来说比较简单,但是在开发的过程中会遇到很多很多的坑,如果没有一些关键点的文字记录,过一段时间之后可能就忘记了某段代码是用于什么⽬的。所以在做完一次需求之后尽量多总结项目中的难点,使用到的框架以及这个框架的原理,以及其中花费时间最多的地方。另外,Bug 最多的地方也要做总结一下原因,这样在面试前就不用把代码再翻一遍,了解一下的项目细节就可以做到游刃有余了。

对于复习,我们要对目前所从事的工作有一个全面的了解,我是通过画脑图来进入这个过程的,我会整体默想一遍大概的知识体系,画成类似下图。回想每个知识点可能考到的内容,记录下⾃⼰模糊的地⽅,然后去看⽹上同学们总结的⾯试题,再对每个题⽬都做⼀下回答。这是⼀个持续迭代的过程。当你预想的问题都可以回答上来的时候,就需要深⼊挖掘⼀下技术细节和深度了,⽐如我⼯作中开发了⼀个 PLT Hook ⼯具,这个⼯具可能是我参考开源项⽬并封装修改过来的,但对其中的细节并没有很了解,这个时候你就要对这个开源项⽬所涉及的内容做⼀次系统学了。

另一方面,面试是一个相互学习的过程,比如我比较擅长的内容,面试官就不一定擅长,所以面试时往自己熟悉的方向走是一个不错的选择,这样会在面试找那个提⾼⾯试官对⾃⼰的级别评价。

算法与数据机构

算法与数据机构基本是面试中的压轴环境,曾经,我到字节面试就是因为算法和数据结构不及格而面试失败。因此,如果要去大厂,算法是⼀定要复习的,在很多⾯试的过程中都会穿插算法题。⾯试的算法题⼀般不会很难,可以分为基础的数据结构,⽐如数组、链表、栈、队列、⼆叉树、堆的使⽤,这⼏种常⻅的数据结构的基础操作⼀定要很熟悉,⽐如链表逆置、删除、获取第 K 个元素、判断是否有环等, ⼆叉树翻转、深度遍历、层级遍历、求树深度、公共⽗节点等。另⼀种是常⻅的搜索、排序算法,这两类算法出现频率很⾼,⼀定要知道它们常⻅的⼏种实现⽅式,⽐如排序⽅式有冒泡、快排、插⼊、归并、堆排序等。注意这⾥⼀定不要简单地去记忆算法实现,因为⾯试的时候可能不会直接让你写出对应的算法,会出⼀些使⽤搜索或者排序算法来实现的题⽬,这类题⽬你可以去 LeetCode 上通过标签过滤出来。

另⼀部分的算法题则侧重于实战,主要集中在贪⼼、动态规划、分治算法、深搜⼴搜等,这⼀类的算法相对需要⼀些技巧性。但⾯试算法题通常不需要太多⾏代码就能完成,⼀般都是在⼏⼗⾏内就能完成的,所以你可以优先去找⼀些经典题⽬来做,⽐如爬楼梯、最⼤⼦序和、最大矩形问题等。但也会有⼀些相对复杂的题⽬是⼏种算法结合在⼀起的,⽐如⼆叉树的最⼤路径和就是深度搜索和动态规划⼀起使⽤的题⽬。除此之外,也可能会遇到通过其他问题引申出的⼀些算法题⽬,⽐如 HashMap 可能会引申出红⿊树的实现等。

接下来就是我整理的一些面试中应该具备的知识点:

第一部分:

Android

  • Android基础
    • FrameLayout(框架布局)
    • LinearLayout(线性布局)
    • AbsoluteLayout(绝对布局)
    • RelativeLayout(相对布局)
    • TableLayout(表格布局)
    • Activity生命周期
    • Activity缓存方法
    • Fragment生命周期
    • Service的两种启动方法
    • ContentProvider使用方法
    • 三种动画的区别
    • Android的数据存储形式
    • Sqlite的基本操作
    • View树绘制流程
    • 你用过什么框架,是否看过源码,是否知道底层原理。
    • 图片缓存
    • IntentService的使用场景与特点
    • Context区别
  • Android内存泄漏总结
  • Handler内存泄漏分析及解决
  • Handler、Looper、Message、MessageQueue基础流程分析
  • Android性能优化
  • ListView详解
  • RecyclerView和ListView的异同
  • AsyncTask源码分析
  • 插件化技术
  • 自定义控件
  • 事件分发机制
  • ANR问题
  • Art和Dalvik的区别
  • Android关于OOM的解决方案
  • Fragment
  • Activity&Fragment
  • SurfaceView
  • Android几种进程
  • APP启动过程
  • Activity启动流程以及界面展示过程
  • 图片三级缓存
  • Bitmap的分析与使用
  • 热修复的原理
  • AIDL
  • Binder机制
  • Zygote和System进程的启动过程
  • Android中的MVC,MVP和MVVM
  • MVP
  • Android开机过程
  • Retrofit源码分析
  • Glide源码分析
  • EventBus用法详解
  • EventBus源码分析
  • Android ORM 框架之 greenDAO 使用心得
  • Data Binding(数据绑定)用户指南
  • RxJava
  • 设计一套图片异步加载缓存方案
  • Android UI适配
  • Gradle
  • 查漏补缺
  • Git操作

设计模式

  • 面向对象六大原则
  • 单例模式
  • Builder模式
  • 原型模式
  • 简单工厂
  • 工厂方法模式
  • 抽象工厂模式
  • 策略模式
  • 状态模式
  • 责任链模式
  • 解释器模式
  • 命令模式
  • 观察者模式
  • 备忘录模式
  • 迭代器模式
  • 模板方法模式
  • 访问者模式
  • 中介者模式
  • 代理模式
  • 组合模式
  • 适配器模式
  • 装饰模式
  • 享元模式
  • 外观模式
  • 桥接模式

第二部分

Java基础

  • 八种基本数据类型的大小,以及他们的封装类
  • Switch能否用string做参数?
  • equals与==的区别
  • Object有哪些公用方法?
  • Java的四种引用,强弱软虚,用到的场景
  • Hashcode的作用
  • String、StringBuffer与StringBuilder的区别
  • try catch finally,try里有return,finally还执行么?
  • Excption与Error区别
  • Excption与Error包结构。OOM你遇到过哪些情况,SOF你遇到过哪些情况
  • OOM
  • Java面向对象的三个特征与含义
  • Override和Overload的含义与区别
  • Interface与abstract类的区别
  • Static class 与non static class的区别
  • java多态的实现原理
  • foreach与正常for循环效率对比
  • 反射机制
  • String类内部实现,能否改变String对象内容
  • try catch 块,try里有return,finally也有return,如何执行
  • 泛型的优缺点
  • 泛型常用特点,List<String>能否转为List<Object>
  • 解析XML的几种方式的原理与特点:DOM、SAX、PULL
  • ArrayList、LinkedList、Vector的底层实现和区别
  • HashMap和HashTable的底层实现和区别,两者和ConcurrentHashMap的区别
  • HashMap的hashcode的作用?什么时候需要重写?如何解决哈希冲突?查找的时候流程是如何?
  • Arraylist和HashMap如何扩容?负载因子有什么作用?如何保证读写进程安全?
  • TreeMap、HashMap、LinkedHashMap的底层实现区别
  • Collection包结构,与Collections的区别
  • Set、List之间的区别是什么?
  • Map、Set、List、Queue、Stack的特点与用法。
  • Java中的内存泄漏
  • String源码分析
  • Java集合框架
  • ArrayList源码剖析
  • LinkedList源码剖析
  • Vector源码剖析
  • HashMap源码剖析
  • HashTable源码剖析
  • LinkedHashMap源码剖析

JVM

  • JVM基础知识
  • JVM类加载机制
  • Java内存区域与内存溢出
  • 垃圾回收算法

Java并发

  • Java并发基础知识
  • 生产者和消费者问题
  • Thread和Runnable实现多线程的区别
  • 线程中断
  • 守护线程与阻塞线程
  • synchronized
  • 多线程环境中安全使用集合API
  • 实现内存可见的两种方法比较:加锁和volatile变量
  • 死锁
  • 可重入内置锁
  • 使用wait/notify/notifyAll实现线程间通信
  • NIO

第三部分

数据结构

  • 数组
  • 链表
  • 栈和队列
  • 字符串

算法

第四部分

网络

操作系统

  • Linux系统的IPC

总结

今天我们并没有涉及太多具体的面试题,而是从宏观层面说明如何准备面试,但面试的准备其实是在我们平时工作过程中一点一滴积累的,复习只是作为一种在面试前巩固知识的手段。复习的过程主要是我们对知识点的整理和总结,你可以想一下在面试的时候可能会遇到的问题,以及该如何去表达。

但是我想说,虽然“临时抱佛脚”的准备可能有时有用,但是在短时间内靠“突击”是很难理解到某个知识点更加深度层次的内容,并且知识⾯的广度也是需要时间和经验去积累的。所以不管你是否需要面试,在平时工作过程中都需要多思考、多训练、多总结,在有需要的时候才可以厚积薄发。

分享面试大厂复习路线

多余的话就不讲了,接下来将分享面试的一个复习路线,如果你也在准备面试但是不知道怎么高效复习,可以参考一下我的复习路线,有任何问题也欢迎一起互相交流,加油吧!

这里给大家提供一个方向,进行体系化的学习:

1、看视频进行系统学习

前几年的Crud经历,让我明白自己真的算是菜鸡中的战斗机,也正因为Crud,导致自己技术比较零散,也不够深入不够系统,所以重新进行学习是很有必要的。我差的是系统知识,差的结构框架和思路,所以通过视频来学习,效果更好,也更全面。关于视频学习,个人可以推荐去B站进行学习,B站上有很多学习视频,唯一的缺点就是免费的容易过时。

另外,我自己也珍藏了好几套视频,有需要的我也可以分享给你。

2、进行系统梳理知识,提升储备

客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

系统学习方向:

  • 架构师筑基必备技能:深入Java泛型+注解深入浅出+并发编程+数据传输与序列化+Java虚拟机原理+反射与类加载+动态代理+高效IO

  • Android高级UI与FrameWork源码:高级UI晋升+Framework内核解析+Android组件内核+数据持久化

  • 360°全方面性能调优:设计思想与代码质量优化+程序性能优化+开发效率优化

  • 解读开源框架设计思想:热修复设计+插件化框架解读+组件化框架设计+图片加载框架+网络访问框架设计+RXJava响应式编程框架设计+IOC架构设计+Android架构组件Jetpack

  • NDK模块开发:NDK基础知识体系+底层图片处理+音视频开发

  • 微信小程序:小程序介绍+UI开发+API操作+微信对接

  • Hybrid 开发与Flutter:Html5项目实战+Flutter进阶

知识梳理完之后,就需要进行查漏补缺,所以针对这些知识点,我手头上也准备了不少的电子书和笔记,这些笔记将各个知识点进行了完美的总结。

3、读源码,看实战笔记,学习大神思路

“编程语言是程序员的表达的方式,而架构是程序员对世界的认知”。所以,程序员要想快速认知并学习架构,读源码是必不可少的。阅读源码,是解决问题 + 理解事物,更重要的:看到源码背后的想法;程序员说:读万行源码,行万种实践。

主要内含微信 MMKV 源码、AsyncTask 源码、Volley 源码、Retrofit源码、OkHttp 源码等等。

4、面试前夕,刷题冲刺

面试的前一周时间内,就可以开始刷题冲刺了。请记住,刷题的时候,技术的优先,算法的看些基本的,比如排序等即可,而智力题,除非是校招,否则一般不怎么会问。

关于面试刷题,我个人也准备了一套系统的面试题,帮助你举一反三:

最后

改变人生,没有什么捷径可言,这条路需要自己亲自去走一走,只有深入思考,不断反思总结,保持学习的热情,一步一步构建自己完整的知识体系,才是最终的制胜之道,也是程序员应该承担的使命。

以上内容均免费分享给大家,需要完整版的朋友,点这里可以看到全部内容。或者关注主页扫描加 微信 获取。

推荐阅读更多精彩内容