前言

面试的顺利与否,直接决定了你是否能获得心仪的offer以及是否能拿到满意的薪资。如果说,简历是获得面试的通行证的话,那面试无疑是决定你是否能获得这份工作的重中之重。因此为自己的面试认真做个准备还是性价比很高的一件事情。

面试前准备的四要素,简历、面经、知己知彼,录音设备。

简历

关于简历怎么写,我后面会出文章详细讲解,这里我就不过多地去赘述,我在这里只是着重强调两点。

  • 第一点就是不会的东西不要写,因为面试官跟你初次见面,对你不是非常了解,一般他问完自己常问的三板斧后,就会结合你的简历去提问,那么你的简历最好能做到趋利避害。也就是引导他问你会的,然后框定大概的考试范围。 所以如果你写在简历上的东西一问三不知,那么在对方的眼里,你可能不光是技术不太行,可能信用方面也差点意思。所以如果你只是一个初学者,或者你离找工作还有一段时间的话,大家可以先给自己维护一份理想中的简历,然后面向简历去学习。当你把自己心目中的样子变成真实的自己后,就可以出去大展宏图了。
  • 第二点其实是再次强调尤其如果你已经有简历,我想说的第二点其实是三年以上的工作经验,那么请务必准备一份没有写期望薪资的简历,用来交给你的技术面试官。 因为确实有很多企业存在着比较严重的薪资倒挂现象,当你有个两三年工作经验后想跳槽的时候,你真的可能会遇到你自己的期望薪资高于对面的当前薪资。为了避免他看到这个数据后心态爆炸,从而影响你面试结果的公平性,那么就没有必要主动让技术面试官知道你的期望薪资。

面经

如果你要面试的是大中型企业Android岗,你很有可能可以在一些app或者网站上刷到这个企业这个职位、别人的面试经验,临时抱抱佛脚。另外,如果你的运气足够好,你正好遇到了面经里面提到的这位面试官,那你的成功率确实会大大增加。虽然不能说是开卷考试吧,但至少客观题你会很容易遇到原题。

如果是面试的小企业的Android岗,没有面经怎么办呢?问题不大,小编在文末给大家准备了《Android面试题汇总+答案解析》,这份面试题是当前互联网企业使用频率最高的面试题,里面每一道题都有详细的答案解析,非常适合作为大家在面试前的复习。

知己知彼

刷完面经后,再花一个小时去了解对方公司,搜索对方公司的主要业务和公司发展历程,准备一个跟对方公司产品业务相关的问题,然后你就可以在面试的过程中,比如自我介绍环节或者最后的向面试官。提问环节向对方传达出一个信息,那就是我不是海投,我是做了功课的,这会大大增加好感,拉近距离。

录音

在面试的前一刻,你可以打开你的录音设备,录音笔也好,手机录音也罢,对你的面试过程进行全程的录音。这分录音主要是两个作用,第一个是把当天没有回答上来的问题记录下来,加强这方面知识点的学习。第二点也是最重要的,通过回放录音你可以发现很多自己平时不易察觉的问题,主要是在表达方式上、用词习惯上,还有语速、音量等等。总之就是自己听听自己当时说的话,自己听起来舒不舒服。

最后

关于《Android面试题汇总+答案解析》面试题的具体展示如下:

一、Java 中深拷贝与浅拷贝的区别?

1、浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。 2、深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。

二、谈谈Error和Exception的区别?

1、Exception是java程序运行中可预料的异常情况,咱们可以获取到这种异常,并且对这种异常进行业务外的处理。 2、Error是java程序运行中不可预料的异常情况,这种异常发生以后,会直接导致JVM不可处理或者不可恢复的情况。所以这 种异常不可能抓取到,比如OutOfMemoryError、NoClassDefFoundError等。

三、什么是反射机制?反射机制的应用场景有哪些?

Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。 应用场景:1. 逆向代码,例如反编译2. 与注解相结合的框架,如 Retrofit3. 单纯的反射机制应用框架,例如 EventBus(事件总线)4. 动态生成类框架 例如Gson

四、谈一谈startService和bindService的区别,生命周期以及使用场景?

  1. 生命周期上的区别 执行startService时,Service会经历onCreate- >onStartCommand。当执行stopService时,直接调用onDestroy方法。调用者如果没有stopService,Service 会一直在后台运行,下次调用者再起来仍然可以stopService。执行bindService时,Service会经历onCreate- >onBind。这个时候调用者和Service绑定在一起。调用者调用unbindService方法或者调用者Context不存在了(如Activity被finish了),Service就会调用onUnbind- >onDestroy。这里所谓的绑定在一起就是说两者共存亡了。多次调用startService,该Service只能被创建一次,即该Service的onCreate方法只会被调用一次。但是每次调用startService,onStartCommand方法都会被调用。Service的onStart方法在API 5时被废弃,替代它的是onStartCommand方法。第一次执行bindService时,onCreate和onBind方法会被调用,但是多次执行bindService时,onCreate和onBind 方法并不会被多次调用,即并不会多次创建服务和绑定服务。
  2. 调用者如何获取绑定后的Service的方法 onBind回调方法将返回给客户端一个IBinder接口实例,IBinder允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。我们需要IBinder对象返回具体的Service对象才能操作,所以说具体的Service对象必须首先实现Binder对象。
  3. 既使用startService又使用bindService的情况 如果一个Service又被启动又被绑定,则该Service会一直在后台运行。首先不管如何调用,onCreate始终只会调用一次。对应startService调用多少次,Service的onStart 方法便会调用多少次。Service的终止,需要unbindService和stopService同时调用才行。不管startService与bindService的调用顺序,如果先调用unbindService,此时服务不会自动终止,再调用stopService之后,服务才会终止;如果先调用stopService,此时服务也不会终止,而再调用unbindService或者之前调用bindService的Context不存在了(如Activity被finish的时候)之后,服务才会自动停止。 那么,什么情况下既使用startService,又使用bindService呢? 如果你只是想要启动一个后台服务长期进行某项任务,那么使用startService便可以了。如果你还想要与正在运行的Service取得联系,那么有两种方法:一种是使用broadcast,另一种是使用bindService。前者的缺点是如果交流较为频繁,容易造成性能上的问题,而后者则没有这些问题。因此,这种情况就需要startService和bindService一起使用了。 另外,如果你的服务只是公开一个远程接口,供连接上的客户端(Android的Service是C/S架构)远程调用执行方法,这个时候你可以不让服务一开始就运行,而只是bindService,这样在第一次bindService的时候才会创建服务的实例运行它,这会节约很多系统资源,特别是如果你的服务是远程服务,那么效果会越明显(当然在Servcie创建的是偶会花去一定时间,这点需要注意)。
  4. 本地服务与远程服务 本地服务依附在主进程上,在一定程度上节约了资源。本地服务因为是在同一进程,因此不需要IPC,也不需要AIDL。相应 bindService会方便很多。缺点是主进程被kill后,服务变会终止。远程服务是独立的进程,对应进程名格式为所在包名加上你指定的android:process字符串。由于是独立的进程,因此在Activity所在进程被kill的是偶,该服务依然在运行。缺点是该服务是独立的进程,会占用一定资源,并且使用AIDL进行IPC稍微麻烦一点。对于startService来说,不管是本地服务还是远程服务,我们需要做的工作都一样简单。

五、谈谈你对 Activity.runOnUiThread 的理解?

一般是用来将一个runnable绑定到主线程,在runOnUiThread源码里面会判断当前runnable是否是主线程,如果是直接run,如果不是,通过一个默认的空构造函数handler将runnable post 到looper里面,创建构造函数handler,会默认绑定一个主线程的looper对象

六、子线程能否更新UI?为什么?

子线程是不能直接更新UI的 注意这句话,是不能直接更新,不是不能更新(极端情况下可更新)绘制过程要保持同步(否则页面不流畅),而我们的主线程负责绘制ui,极端情况就是,在Activity的onResume(含)之前的生命周期中子线程都可以进行更新ui,也就是onCreate,onStart和onResume,此时主线程的绘制还没开始。

七、你了解 Android 系统启动流程吗?

当按电源键触发开机,首先会从ROM中预定义的地方加载引导程序BootLoader 到 RAM中,并执行BootLoader程序启动Linux Kernel,然后启动用户级别的第一个进程: init 进程。init 进程会解析init.rc脚本做一些初始化工作,包括挂载文件系统创建工作目录以及启动系统服务进程等,其中系统服务进程包括 Zygote、service manager、media 等。在 Zygote中会进一步去启动 system_ server进程,然后在 system_server 进程中会启动AMS、WMS、PMS等服务,等这些服务启动之后,AMS中就会打开Launcher应用的home Activity,最终就看到了手机的“桌面”。

八、Binder有什么优势

性能方面

  • 共享内存 0次数据拷贝
  • Binder 1次数据拷贝
  • Socket/管道/消息队列 2次数据拷贝

稳定性方面

  • Binder:基于C/S架构,客户端 (Client) 有什么需求就丢给服务端 (Server) 去完成,架构清晰、职责明确又相互独立,自然稳定性更好
  • 共享内存:虽然无需拷贝,但是控制复杂,难以使用
  • 从稳定性的角度讲,Binder机制是优于内存共享的。

安全性方面

  • 传统的IPC没有任何安全措施,安全依赖上层协议来确保。
  • 传统的IPC方法无法获得对方可靠的进程用户ID/进程UI (UID/PID) ,从而无法鉴别对方身份。
  • 传统的IPC只能由用户在数据包中填入UID/PID,容易被恶意程序利用。
  • 传统的IPC访问接入点是开放的,无法阻止恶意程序通过猜测接收方地址获得连接。
  • Binder既支持实名Binder,又支持匿名Binder,安全性高。

九、Binder机制是如何跨进程的

  1. Binder驱动
  • 在内核空间创建一块接收缓存区,
  • 实现地址映射:将内核缓存区、接收进程用户空间映射到同一接收缓存区
  1. 发送进程通过系统调用 (copy_from_user) 将数据发送到内核缓存区。由于内核缓存区和 接收进程用户空间存在映射关系,故相当于也发送了接收进程的用户空间,实现了跨进程通信

十、简述下Handler机制的总体原理

  1. Looper 准备和开启轮循: Looper#prepare()初始化线程独有的 Looper 以及 MessageQueue Looper#loop()开启死循环读取 MessageQueue 中下一个满足执行时间的 Message 尚无 Message 的话,调用 Native 侧的 pollOnce()进入无限等待存在 Message,但执行时间 when 尚未满足的话,调用 pollOnce()时传入剩余时长参数进入有限等待
  2. Message 发送、入队和出队: Native 侧如果处于无限等待的话:任意线程向 Handler 发送 Message 或 Runnable 后,Message 将按照 when 条件的先后,被插 入 Handler 持有的 Looper 实例所对应的 MessageQueue 中适当的位置。 MessageQueue 发现有合适的 Message 插入后将调用 Native 侧的 wake() 唤醒无限等待的线程。这将促使 MessageQueue 的读取继续进入下一次循环,此刻 Queue 中已有满足条件的 Message 则 出队返回给 Looper Native 侧如果处于有限等待的话:在等待指定时长后 epoll_wait 将返回。线程继续读取 MessageQueue, 此 刻因为时长条件将满足将其出队 Looper 处理Message 的实现:
  3. Looper 得到 Message 后回调 Message 的 callback 属性即 Runnable,或依据 target 属性即 Handler,去执行 Handler 的回调。存在 mCallback属性的话回调 Handler$Callback 反之,回调 handleMessage()

由于文章篇幅有限,不能将完整的面试题全部展示出来,有需要完整面试题和答案解析的朋友,可以点击下方课程链接详细了解!!!

https://edu.51cto.com/course/32703.html

Android程序员掌握这些面试技巧,offer拿到手软_Android