阿里P8大牛:你还在拿5000块的死工资吗?有时候逆袭就在一瞬之间 前言

前言

不知道大家面试的时候,有没有遇到这种情况,面试工资谈的是10K,最后干着40K的活!说着冠冕堂皇,提升大家能力的话,做着死命压榨员工,996996.成了程序员心里的魔咒!

初级安卓开发工程师(10K-15K)

掌握扎实的java基础,了解各种设计模式,熟练掌握Android UI控件、Android Java层API的相关使用。往中级层次发展时,继续深入学习java编程技术,掌握更多Android开发需要的库,还要精通ml、json解析,会做socket c/s端的程序。

中级安卓开发工程师(15K-30K)

除了上面提到的必备技能外,中级开发人员需要延伸到精通NDK JNI方式的开发,熟悉Android framework,会移植类似Fmpeg、Mplayer这样的开源项目,并在Android上运行。

高级安卓开发工程师(50K-100K)

作为高级app开发工程师,你只需了解,并不需要亲自操作初级和中级工程师的工作流程,但是,你需要有一个整体知识构架,安卓开发各方面所涉及的知识你都有要了解,并有自己独到的见解。需要熟练掌握Linux驱动开发,并对Linux内核结构很精通,掌握Android移植,包括硬件移植。

现如今做开发的门槛越来越高,市场一直在升级,很多人说Android不好做了,其实是市场对Android程序员的要求越来越高了!

但是,术业有专攻,总有一些技术牛逼的程序员可以吊打、碾压面试官!

本人经常隔段时间就偷偷投点简历,请假出去面试几次,目的不是想跳槽,主要是为了看看市场上的技术流行趋势,顺便检验一下自己的水平,当然,如果面到了心仪的公司或者大厂,那不是更好嘛,哈哈哈!

前段时间收到了字节跳动的面试,虽然有点小震惊,但还是用平常心对待了。结果一不小心,面试的时候就吊打了面试官。


阿里面试题

说下你所知道的设计模式与使用场景

a.建造者模式:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
使用场景比如最常见的AlertDialog,拿我们开发过程中举例,比如Camera开发过程中,可能需要设置一个初始化的相机配置,设置摄像头方向,闪光灯开闭,成像质量等等,这种场景下就可以使用建造者模式

装饰者模式:动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。装饰者模式可以在不改变原有类结构的情况下曾强类的功能,比如Java中的BufferedInputStream 包装FileInputStream,举个开发中的例子,比如在我们现有网络框架上需要增加新的功能,那么再包装一层即可,装饰者模式解决了继承存在的一些问题,比如多层继承代码的臃肿,使代码逻辑更清晰
观察者模式:
代理模式:
门面模式:
单例模式:
生产者消费者模式:

java语言的特点与OOP思想

这个通过对比来描述,比如面向对象和面向过程的对比,针对这两种思想的对比,还可以举个开发中的例子,比如播放器的实现,面向过程的实现方式就是将播放视频的这个功能分解成多个过程,比如,加载视频地址,获取视频信息,初始化解码器,选择合适的解码器进行解码,读取解码后的帧进行视频格式转换和音频重采样,然后读取帧进行播放,这是一个完整的过程,这个过程中不涉及类的概念,而面向对象最大的特点就是类,封装继承和多态是核心,同样的以播放器为例,一面向对象的方式来实现,将会针对每一个功能封装出一个对象,吧如说Muxer,获取视频信息,Decoder,解码,格式转换器,视频播放器,音频播放器等,每一个功能对应一个对象,由这个对象来完成对应的功能,并且遵循单一职责原则,一个对象只做它相关的事情

说下java中的线程创建方式,线程池的工作原理。

java中有三种创建线程的方式,或者说四种
1.继承Thread类实现多线程
2.实现Runnable接口
3.实现Callable接口
4.通过线程池

线程池的工作原理:线程池可以减少创建和销毁线程的次数,从而减少系统资源的消耗,当一个任务提交到线程池时
a. 首先判断核心线程池中的线程是否已经满了,如果没满,则创建一个核心线程执行任务,否则进入下一步
b. 判断工作队列是否已满,没有满则加入工作队列,否则执行下一步
c. 判断线程数是否达到了最大值,如果不是,则创建非核心线程执行任务,否则执行饱和策略,默认抛出异常

说下 handler 原理

Handler,Message,looper 和 MessageQueue 构成了安卓的消息机制,handler创建后可以通过 sendMessage 将消息加入消息队列,然后 looper不断的将消息从 MessageQueue 中取出来,回调到 Hander 的 handleMessage方法,从而实现线程的通信。

从两种情况来说,第一在UI线程创建Handler,此时我们不需要手动开启looper,因为在应用启动时,在ActivityThread的main方法中就创建了一个当前主线程的looper,并开启了消息队列,消息队列是一个无限循环,为什么无限循环不会ANR?因为可以说,应用的整个生命周期就是运行在这个消息循环中的,安卓是由事件驱动的,Looper.loop不断的接收处理事件,每一个点击触摸或者Activity每一个生命周期都是在Looper.loop的控制之下的,looper.loop一旦结束,应用程序的生命周期也就结束了。我们可以想想什么情况下会发生ANR,第一,事件没有得到处理,第二,事件正在处理,但是没有及时完成,而对事件进行处理的就是looper,所以只能说事件的处理如果阻塞会导致ANR,而不能说looper的无限循环会ANR

另一种情况就是在子线程创建Handler,此时由于这个线程中没有默认开启的消息队列,所以我们需要手动调用looper.prepare(),并通过looper.loop开启消息

主线程Looper从消息队列读取消息,当读完所有消息时,主线程阻塞。子线程往消息队列发送消息,并且往管道文件写数据,主线程即被唤醒,从管道文件读取数据,主线程被唤醒只是为了读取消息,当消息读取完毕,再次睡眠。因此loop的循环并不会对CPU性能有过多的消耗。

内存泄漏的场景和解决办法

1.非静态内部类的静态实例
非静态内部类会持有外部类的引用,如果非静态内部类的实例是静态的,就会长期的维持着外部类的引用,组织被系统回收,解决办法是使用静态内部类

2.多线程相关的匿名内部类和非静态内部类
匿名内部类同样会持有外部类的引用,如果在线程中执行耗时操作就有可能发生内存泄漏,导致外部类无法被回收,直到耗时任务结束,解决办法是在页面退出时结束线程中的任务

3.Handler内存泄漏
Handler导致的内存泄漏也可以被归纳为非静态内部类导致的,Handler内部message是被存储在MessageQueue中的,有些message不能马上被处理,存在的时间会很长,导致handler无法被回收,如果handler是非静态的,就会导致它的外部类无法被回收,解决办法是1.使用静态handler,外部类引用使用弱引用处理2.在退出页面时移除消息队列中的消息

4.Context导致内存泄漏
根据场景确定使用Activity的Context还是Application的Context,因为二者生命周期不同,对于不必须使用Activity的Context的场景(Dialog),一律采用Application的Context,单例模式是最常见的发生此泄漏的场景,比如传入一个Activity的Context被静态类引用,导致无法回收

5.静态View导致泄漏
使用静态View可以避免每次启动Activity都去读取并渲染View,但是静态View会持有Activity的引用,导致无法回收,解决办法是在Activity销毁的时候将静态View设置为null(View一旦被加载到界面中将会持有一个Context对象的引用,在这个例子中,这个context对象是我们的Activity,声明一个静态变量引用这个View,也就引用了activity)

6.WebView导致的内存泄漏
WebView只要使用一次,内存就不会被释放,所以WebView都存在内存泄漏的问题,通常的解决办法是为WebView单开一个进程,使用AIDL进行通信,根据业务需求在合适的时机释放掉

7.资源对象未关闭导致
如Cursor,File等,内部往往都使用了缓冲,会造成内存泄漏,一定要确保关闭它并将引用置为null

8.集合中的对象未清理
集合用于保存对象,如果集合越来越大,不进行合理的清理,尤其是入股集合是静态的

9.Bitmap导致内存泄漏
bitmap是比较占内存的,所以一定要在不使用的时候及时进行清理,避免静态变量持有大的bitmap对象

10.监听器未关闭
很多需要register和unregister的系统服务要在合适的时候进行unregister,手动添加的listener也需要及时移除

如何避免OOM?

1.使用更加轻量的数据结构:如使用ArrayMap/SparseArray替代HashMap,HashMap更耗内存,因为它需要额外的实例对象来记录Mapping操作,SparseArray更加高效,因为它避免了Key Value的自动装箱,和装箱后的解箱操作

2.便面枚举的使用,可以用静态常量或者注解@IntDef替代

3.Bitmap优化:
a.尺寸压缩:通过InSampleSize设置合适的缩放
b.颜色质量:设置合适的format,ARGB_6666/RBG_545/ARGB_4444/ALPHA_6,存在很大差异
c.inBitmap:使用inBitmap属性可以告知Bitmap解码器去尝试使用已经存在的内存区域,新解码的Bitmap会尝试去使用之前那张Bitmap在Heap中所占据的pixel data内存区域,而不是去问内存重新申请一块区域来存放Bitmap。利用这种特性,即使是上千张的图片,也只会仅仅只需要占用屏幕所能够显示的图片数量的内存大小,但复用存在一些限制,具体体现在:在Android 4.4之前只能重用相同大小的Bitmap的内存,而Android 4.4及以后版本则只要后来的Bitmap比之前的小即可。使用inBitmap参数前,每创建一个Bitmap对象都会分配一块内存供其使用,而使用了inBitmap参数后,多个Bitmap可以复用一块内存,这样可以提高性能

4.StringBuilder替代String: 在有些时候,代码中会需要使用到大量的字符串拼接的操作,这种时候有必要考虑使用StringBuilder来替代频繁的“+”

5.避免在类似onDraw这样的方法中创建对象,因为它会迅速占用大量内存,引起频繁的GC甚至内存抖动

6.减少内存泄漏也是一种避免OOM的方法


面试时要注意,准备什么?

注意

第一个问题就是“不求甚解”。

何为不求甚解?其大多数的问题就是在于大量的使用第三方的jar包,问他个原理一点也答不上来,甚至是最基础的。举个例子说明,比如我问他json数据怎么解析,都知道哪些解析器,直接不知道,因为现在的开发者都直接去使用GJSON,从来不去了解解析的整个过程和原理,更不会写。虽然用google提供的工具可以轻松实现,但是原理和过程还是得要学习的。学了总会有用,现在第三方的jar包多的是,封装的也都比较好,不是不能用,但是一定要学习原理和机制,这样才能提高自己,举一反三,如果只会用第三方,只会粘贴复制,你还仅仅处在码畜的级别,甚至有可能还不如。这个问题你犯了吗?记得要对号入座哦!

第二个问题就是不思进取,或者说叫技术落后。

怎么说呢,技术是不断在进步的,不断的在革新,尤其是我们程序员这个行业。很多程序猿一旦学习完了,工作了,虽然用旧的知识和技术也能实现这种效果,但是从不会考虑效率,不去学习新的技术,明明有更好的控件提供了,也不知道,或者知道并不去学习,还停留在以前的知识,面试时要的工资还挺高。再举个例子,面试时,问他们ListView的复用,大家答的都挺好的,都非常明白,我再问一句:Android5.0提供了新的控件替代了它,你们知道吗?用过吗?就全都哑火了。

我都不知道该说什么好?程序猿之所以累,之所以叫猿就是因为他要时时刻刻保持一颗活到老学到老的心,要利用最新的技术知识解决新的难题。

讲到这里,两个问题已经讲完了,不知道你自己是否也有这样的毛病呢?请记得对号入座哦。现在我们再说一说面试者的另一方面的事,那就是简历的书写。

我相信大家写面试简历肯定都有夸大的成分,都会吹牛,这不要紧,牛吹好了,工资自然高,但是别吹过头,面试的时候我看到面试者的简历时,给我的感觉是:我靠,好屌,好厉害啊!这时一个情不自禁的想法就来了,我要问问他这方面的知识。

比如:一个面试应用层开发的,非把自己底层开发也写的很牛逼,你真的像你简历上写的那样“精通”吗?面试者把简历写的每个技术知识点都是精通与熟练,有时候,反而是搬起石头砸了自己的脚,吹牛可以,夸大也可以,都是为了生存吗?但是要适可而止,要在自己掌握的一个度里,这样既能自己面试的漂亮和顺利,给面试官也有好的印象,这样的情况不招你,招谁啊?

准备

  • 简历

先大概归纳下个人在简历筛选上的一些偏好吧:

1.技术人员的简历不要太多的页数,最多两个足矣,一页最好;

2.个人的重要的基本信息还是要有的,如性别、出生日期(因为有些面试官会在意年龄)、籍贯、基本的联系方式、毕业院校和专业、毕业时间等;

3.言简意赅,突出重点和亮点。

其实,于招聘企业来说,在发出招聘信息时,已经有了一个大概的招聘要求,对于面试官来说,心中也已经有一定的。在庞杂的众多简历中,如果能够脱引而出,是每个应聘者需要好好考虑的。有时候,经常会听到这样一种观点,技术人员没必要弄那些虚的,扎扎实实的技术实力充分的体现在面试过程中就可以了。其实,我对此并不赞同。

1.简历简历,是陈述一个人的基本成长经历,尤其是应聘目标岗位要求相关的经历。这直接反应的是岗位的匹配度;

2.简历不仅仅是简历本身,同时也是应聘者对于过往经历的回顾、总结与提炼,一份认真准备的简历也是应聘者应聘诚意的反应;

3.认真准备的简历,与虚不虚没有关系,扎扎实实的技术实力固然可以充分的体现在面试过程中,但简历中的重点和亮点可以使得面试官更好的提问和交流,为自己加分。

  • 刷题
    当然也是最重要的,毕竟我是有好几年没有过正规面试的经历了,于是问我在阿里的同学要来了一份他们公司P8整理的一系列大厂面试题,刷到天昏地暗,如今我也已经入职了阿里,这些面试题对于我来说也没什么太大的用处,所以在这里无偿的分享给大家。

如果需要PDF版本可以在群文件夹里,自行领取!

进阶学习视频

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

面试成功其实是必然的,因为我做足了充分的准备工作,包括刷题啊,看一些Android核心的知识点,看一些面试的博客吸取大家面试的一些经验,下面这份PDF是我翻阅了差不多1个月左右一些Android大博主的博客从他们那里取其精华去其糟泊所整理出来的一些Android的核心知识点, 全部都是精华中的精华,我能面试到现在2-2资深开发人员跟我整理的这本Android核心知识点有密不可分的关系,在这里本着共赢的心态分享给各位朋友。

这份PDF囊括了JVM,Java集合,Java多线程并发,Java基础,生命周期,微服务, 进程,Parcelable 接口,IPC,屏幕适配,线程异步,ART,架构,Jetpack,NDK开发,计算机网络基础,类加载器,Android 开源库源码分析,设计模式汇总,Gradle 知识点汇总......

由于篇幅有限,就不做过多的介绍,大家请自行脑补,需要这份Android核心知识点及大厂面试题答案的朋友

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章