不得不说,前两年的移动开发确实很火,能够说随便能鼓捣出来点东西都很容易找到工做。而如今明显降温了,对人才的要求也愈来愈苛刻,因此跟前两年比需求确实少了不少。可是安卓不只仅局限于手机,智能家居车载系统电视机顶盒智能机器人的触摸板设置大部分都是搭载的安卓系统,因此市场的需求仍是很大的。react
本文但愿达到的目的是为职场新人和毕业生提供一个面试经验的分享,使读者在找工做时有一个参考少走弯路,经过本文的阅读将收获到:android
对于咱们程序员而言,面试就是将本身所学的技术与面试官表达出来。之前上学准备找工做的时候,发现最早找到工做的不是技术最好的而是善于沟通活跃度高的人,而我听的最多的抱怨是 “为何我明明知道这个东西,面试的时候殊不知从何提及”。程序员
本文会从个人自身经历出发谈一谈面试前如何作好充分准备,怎么流畅的表达本身的技术,以及进入项目时如何从一开始的手足无措、盲目下手到后来的淡定从容。面试
简历编写算法
对于任何阶段的面试者来讲拥有一份精致的简历是很重要的,所谓精致就是要突出重点,特别对于技术类的简从来说废话越少越好。好的简历要有辨识度,记得之前听 HR 聊天时说:“明明没啥东西写了两三页,看到后面才知道他要干吗,简直浪费纸”大部分人写简历都会用网上的模板,固然用模板写会节省很大的人力并且格式也更好看。然而模板上面有不少套话,数据库
这段自我评价估计不少人都会感到很熟悉,甚至一部分人的简历上面还有,由于每一个人均可以这样写。想想这种评价 HR 天天看了多少遍,再看下面这张简历案例,在评价栏罗列出本身的技术点,突出重点一目了然。设计模式
刚毕业出来找工做的同窗来讲,没有上图有那么多干货能够写,怎么才能突出重点呢,教一个小技巧,你们能够浏览几十家不一样类型公司的任职要求,你会发现有两到三条几乎是相同的,那么这两到三条技术点就是你必需要掌握的了,并且技术评价里面必定要写出来。缓存
简历编写要适度不要给本身挖坑,掌握不能写成精通了解不能写成掌握,精通在了解怎么用的同时还要了解它的底层实现,掌握的话就要知道它的用法以及出现问题怎么解决。了解的话就要知道这个技术点能够处理什么问题,了解一些 API 怎么调用。性能优化
技能储备微信
Java 基础知识方面须要掌握的有:面向对象的理解、基本类型与引用类型、构造方法、经常使用类(内部类、匿名类、抽象类)、三大特性(封装、继承、多态)、重写与重载、接口与接口的实现等等。这些问题面试官会在掌握的层面上去问你,主要是考察你的基础知识是否扎实,毕竟安卓是用 Java 编写的。
Android 方面须要掌握的有:四大组件的简单使用、activity 的生命周期、fragment 的绑定、activity 和 fragment 之间的传值、 recyclerview 实现列表九宫格瀑布流式布局的实现、viewHolder 的复用问题、数据存储的几种方式的特色、经常使用框架 Glide、Retrofit、eventBus、butterknife 的使用。
Java 基础知识须要掌握的有:对于两到三年的安卓程序员来讲,Java 不只仅是停留在一些基础知识的使用上了,而是在用的同时要有本身的理解。好比说封装,面试官不会问你什么是封装,而是会问你封装过公司的哪些代码/功能,你是如何封装的。这个时候考察的就是你是会写代码仍是只会模仿代码,若是没有本身在项目中封装过代码的话能够去阅读下网上一些优秀的框架的源码学习一下别人是怎么封装的。
固然不只仅是封装还有不少知识点都要按照这个要求去掌握,好比:Java 泛型、反射、集合框架、接口与抽象类、设计模式等等。掌握这些除了看视频学习还能够阅读一些优秀的源码。不懂的地方再查一查博客,理解透了后必定要在本身项目上运用,这样学习才能印象深入面试官问到也能有列可举。
Android 方面须要掌握的有:APP 启动原理,想要详细了解的能够看个人另外一篇 chat (APP 启动原理及启动优化详解 )、图片压缩与性能优化、自定义 view 、事件分发流程、屏幕适配、组件化和插件化、Glide 的缓存与复用、OkHttp 的责任链与链接池、序列化与反序列化、分析一个你最熟练框架的源码等等。能够看到,对于两到三年的程序员来讲不只掌握的知识点更多,并且还须要对原理有必定的了解。
大厂面试经历
本人刚出来找工做的时候面试了不少家,那时候是移动开发的爆发时期,其中有万能钥匙等中大型公司也有一些刚创业的小公司,固然大厂最终面试失败了。记得去万能钥匙面试的时候,去面试的人特别的多,须要在大厅等待,一批一批的去面试,先是群面,了解基本状况事后,就是单独面谈等待面试,总共三轮面试,面试官会通知面试结果出来的时间。
面试官提到的问题有:为何从上一家离职、如何看待咱们公司、本身之后的职业规划是什么、技术方面问了 Java 的内存回收机制,内存溢出和内存泄漏、如何避免 OOM 异常、什么是 AIDL,AIDL 怎么使用、 android 线程间通讯有那几种方式、Glide 三级缓存怎么实现的。
大小厂考察点的区别
流程比较多,通常会有三面以上,首先会有一套面试题等着你,固然不是全部公司都有面试题,只不过大厂有面试题的几率会高些,其次技术主管面试,而后技术经理面试,人事会跟你介绍公司的发展业务公司福利工做时间等等。大厂的开发通常是分模块开发,每一个人单独负责某一个模块,因此要求你要有本身的优点点,好比你会写自定义组件,视频模块,对 NDK 深有研究等等。
流程少,有可能一面过了就叫你来上班了。小公司面试必定要问清楚工资何时发,月初发说明公司资金充足,月中旬发是正常的,若是月末才发的话公司资金紧张极可能出现财务危机。还有五险一金有没有,有的话试用期有没有,目前还有一部分公司没有五险一金的,并且大部分公司试用期不交五险一金。关于五险一金的重要性你们能够去百度搜一搜,限购令出来后这个更加剧要了。
关于技术方面的区别就是,小公司通常都是一我的开发,要求你知道整个项目的开发流程,可是对于技术深度要求不高(仅仅对于初级程序员来讲,高级架构师就另说了)。面试以前多准备些项目去演示,有些人说懂技术的都不看做品的,可是对于小公司就不一样了,有可能面试你的是产品经理、后台人员等等,对安卓了解的也不是很深,这时候有几个好的做品演示必定会给你的面试加很多分。
如下五个问题本人面试的时候都被问到过,也做为面试官考察过别人,算是比较有表明性的题目。
Activity 的生命周期
这个问题的关键是理解,这道面试题还有其余的问法,好比:问onStart()、与 onResume() 有什么区别?什么状况下 Activity 走了onCreat(),而不走 onStart()?
请介绍下 Android 的数据存储方式。
使用 SharedPreferences 存储数据;文件存储数据;SQLite 数据库存储数据;使用 ContentProvider 存储数据;网络存储数据。
Preference,File, DataBase 这三种方式分别对应的目录是 /data/data/Package Name/Shared_Pref, /data/data/Package Name/files, /data/data/Package Name/database 。
首先说明 SharedPreferences 存储方式,它是 Android 提供的用来存储一些简单配置信息的一种机制,例如:登陆用户的用户名与密码。其采用了 Map 数据结构来存储数据,以键值的方式存储,能够简单的读取与写入,具体实例以下:
void ReadSharedPreferences(){ String strName,strPassword; SharedPreferences user = getSharedPreferences(“user_info”,0); strName = user.getString(“NAME”,””); strPassword = user getString(“PASSWORD”,””); } void WriteSharedPreferences(String strName,String strPassword){ SharedPreferences user = getSharedPreferences(“user_info”,0); uer.edit(); user.putString(“NAME”, strName); user.putString(“PASSWORD” ,strPassword); user.commit(); }
数据读取与写入的方法都很是简单,只是在写入的时候有些区别:先调用 edit() 使其处于编辑状态,而后才能修改数据,最后使用 commit() 提交修改的数据。实际上 SharedPreferences 是采用了 XML 格式将数据存储到设备中,在 DDMS 中的 File Explorer 中的 /data/data/<package name>/shares_prefs 下。使用 SharedPreferences 是有些限制的:只能在同一个包内使用,不能在不一样的包之间使用。
文件存储方式是一种较经常使用的方法,在 Android 中读取/写入文件的方法,与 Java 中实现 I/O 的程序是彻底同样的,提供了 openFileInput() 和openFileOutput() 方法来读取设备上的文件。具体实例以下:
String fn = “moandroid.log”; FileInputStream fis = openFileInput(fn); FileOutputStream fos = openFileOutput(fn,Context.MODE_PRIVATE);
网络存储方式,须要与 Android 网络数据包打交道,关于 Android 网络数据包的详细说明,请阅读 Android SDK 引用了 Java SDK 的哪些package?。
activity的启动模式有哪些?是什么含义?
在 Android 里,有 4 种 activity 的启动模式,分别为:
“standard” (默认)
“singleTop”
“singleTask”
“singleInstance”
它们主要有以下不一样:
“standard” 和 ”singleTop” 的 activity 的目标 task,和收到的 Intent 的发送者在同一个 task 内,除非 intent 包括参数 FLAG_ACTIVITY_NEW_TASK。
若是提供了 FLAG_ACTIVITY_NEW_TASK 参数,会启动到别的 task 里。
“singleTask” 和 ”singleInstance” 老是把 activity 做为一个 task 的根元素,他们不会被启动到一个其余 task 里。
“standard” 和 ”singleTop” 能够被实例化屡次,而且存在于不一样的 task 中,且一个 task 能够包括一个 activity 的多个实例。
“singleTask” 和 ”singleInstance” 则限制只生成一个实例,而且是 task 的根元素。 singleTop 要求若是建立 intent 的时候栈顶已经有要建立的 Activity的实例,则将 intent 发送给该实例,而不发送给新的实例。
“singleInstance” 独占一个 task,其它 activity 不能存在那个 task 里;若是它启动了一个新的 activity,无论新的 activity 的 launch mode 如何,新的activity 都将会到别的 task 里运行(如同加了 FLAG_ACTIVITY_NEW_TASK参数)。
而另外三种模式,则能够和其它 activity 共存。
“standard” 对于没一个启动 Intent 都会生成一个 activity 的新实例。
“singleTop” 的 activity 若是在 task 的栈顶的话,则不生成新的该 activity 的实例,直接使用栈顶的实例,不然,生成该 activity 的实例。
好比如今 task 栈元素为 A-B-C-D(D在栈顶),这时候给 D 发一个启动 intent,若是 D 是 “standard” 的,则生成 D 的一个新实例,栈变为 A-B-C-D-D。
若是 D 是 singleTop 的话,则不会生产 D 的新实例,栈状态仍为 A-B-C-D。
若是这时候给 B 发 Intent 的话,无论 B 的 launchmode 是 ”standard” 仍是 “singleTop” ,都会生成 B 的新实例,栈状态变为 A-B-C-D-B。
“singleInstance” 是其所在栈的惟一 activity,它会每次都被重用。
“singleTask” 若是在栈顶,则接受 intent,不然,该 intent 会被丢弃,可是该 task 仍会回到前台。
当已经存在的 activity 实例处理新的 intent 时候,会调用 onNewIntent() 方法 若是收到 intent 生成一个 activity 实例,那么用户能够经过 back 键回到上一个状态;若是是已经存在的一个 activity 来处理这个 intent 的话,用户不能经过按 back 键返回到这以前的状态。
什么是 ANR 如何避免它?
ANR:Application Not Responding。在 Android 中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应,当用户操做的在 5s 内应用程序没能作出反应,BroadcastReceiver 在 10 秒内没有执行完毕,就会出现应用程序无响应对话框,这既是 ANR。
避免方法:Activity 应该在它的关键生命周期方法(如 onCreate() 和onResume())里尽量少的去作建立操做。潜在的耗时操做,例如网络或数据库操做,或者高耗时的计算如改变位图尺寸,应该在子线程里(或者异步方式)来完成。主线程应该为子线程提供一个 Handler,以便完成时可以提交给主线程。
注册广播有几种方式,这些方式有何优缺点?请谈谈 Android 引入广播机制的用意。
首先写一个类要继承 BroadcastReceiver
第一种:在清单文件中声明,添加
第二种使用代码进行注册如
两种注册类型的区别是:
搭建项目的主流框架集
Dagger2+RxJava+Retrofit+MVP 是本人目前用的框架集,目前使用的很普遍, 四个相结合,组成项目的优美总体架构。 须要导入的包
> dependencies { // 网络请求 compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:adapter-rxJava:2.0.1' compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4' compile 'com.squareup.retrofit2:converter-scalars:2.0.0-beta4' compile 'com.squareup.okhttp3:okhttp:3.2.0' // 注解 compile 'com.google.dagger:dagger:2.0.2' apt 'com.google.dagger:dagger-compiler:2.0.2' provided 'org.glassfish:Javax.annotation:10.0-b28' compile 'com.jakewharton:butterknife:7.0.1' // Rx compile 'io.reactivex:rxandroid:1.1.0' compile 'io.reactivex:rxJava:1.1.5' }
下面是 MVP 的架构图
如上图所示
View 与 Model 并不直接交互,而是使用 Presenter 做为 View 与 Model 之间的桥梁。
其中 Presenter 中同时持有 view 层以及 Model 层的 Interface 的引用,View 层持有 Presenter 层 Interface 的引用。当 View 层某个界面须要展现某些数据的时候,首先会调用 Presenter 层的某个接口,而后 Presenter 层会调用 Model 层请求数据。
当 Model 层数据加载成功以后会调用 Presenter 层的回调方法通知 Presenter 层数据加载完毕。
最后 Presenter 层再调用 View 层的接口将加载后的数据展现给用户。这就是 MVP 模式的整个核心过程,若是你是面试初级安卓开发,面试官应该只会让你阐述下整个调用过程,只要你能流畅的说完整个过程应该差很少了。
Dagger2 的流程图
什么是 Dagger2
Dagger2 是一个依赖注入框架,butterknife 也是一个依赖注入框架。不过 butterknife,最多叫奶油刀,Dagger2 被叫作利器啊,他的主要做用,就是对象的管理,其目的是为了下降程序耦合。
Dagger2 的优势
和 ButterKnife 库定义了view,事件处理以及资源的引用同样,Dagger2 提供全局对象引用的简易访问方式。声明了单例的实例均可以使用 @inject 进行访问。好比下面的 MyTwitterApiClient 和SharedPreferences 的实例:
> public class MainActivity extends Activity { @Inject MyTwitterApiClient mTwitterApiClient; @Inject SharedPreferences sharedPreferences; public void onCreate(Bundle savedInstance) { // assign singleton instances to fields InjectorClass.inject(this); }
Dagger2 会经过依赖关系而且生成易懂易分析的代码。之前经过手写的大量模板代码中的对象引用将会由它给你建立并传递到相应对象中。所以你能够更多的关注模块中构建的内容而不是模块中的对象实例的建立顺序。
由于依赖关系已经为咱们独立出来,因此咱们能够轻松的抽取出不一样的模块进行测试。依赖的注入和配置独立于组件以外。由于对象是在一个独立、不耦合的地方初始化,因此当注入抽象方法的时候,咱们只须要修改对象的实现方法,而不用大改代码库。依赖能够注入到一个组件中:咱们能够注入这些依赖的模拟实现,这样使得测试更加简单。
咱们不只能够轻松的管理全局实例对象,也可使用 Dagger2 中的 scope 定义不一样的做用域。(好比根据 user session、activity 的生命周期)
Retrofit 是 Square 开发的一个 Android 和 Java 的 REST 客户端库。这个库很是简单而且具备不少特性,相比其余的网络库,更容易让初学者快速掌握。
建立 Retrofit 实例时须要经过 Retrofit.Builder,并调用 baseUrl 方法设置 URL。
接口定义
以获取时间列表为例
> public interface TimeService { > @GET("getTimes?") Call< ResponseBody > getTimes (@Query("month") String month); }
注意,这里是 interface 不是 class,因此咱们是没法直接调用该方法,咱们须要用 Retrofit 建立一个 TimeService 的代理对象。
TimeService timeService= createRetrofit().create(TimeService .class);
接口调用
> Call<ResponseBody> mService= timeService.getTimes ("1"); mService.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { try { Log(response.body().string()); } catch (IOException e) { e.printStackTrace(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { t.printStackTrace(); } });
如何快速理解项目进行二次开发
当咱们进入一个新公司工做,有可能接手的不是一个新项目而是维护别人开发的项目,面对庞大的项目不知从何下手。在这里我要告诉你们的是,拿到项目的时候不要盲目的进行开发而是阅读项目源码。阅读源码首先浏览项目结构,
经过这张结构图能够了解项目用的是 MVP 架构,有两个 lib 一个和 service 有关 一个和图片处理有关。而后再阅读 build.gradle 文件,里面有项目中用到的第三方库的引用地址,知道项目中用到了哪些技术,若是有不熟悉的第三方库就能够根据这个地址去查找资源熟悉调用方式项目中用到的模块,往后逐渐研究库的源码以及实现原理。等这些了解的差很少了,再看一看需求文档和设计图,对着需求走一遍流程,主要记录 activity 之间的跳转,能够画一张类之间跳转的结构图,这样整个跳转的逻辑会更清晰。
还有两个值得阅读的是:项目中的工具类和封装的组件。相信很多人遇到过,在网上找了好久的一个处理数据的方法,过了数日发现项目的工具类中有直接就能够拿来用。封装的组件也和工具相似能够直接拿来用的,在后面的开发也提倡你们将项目组件化。
腾讯
synchronize 用法
volatile 用法
动态权限适配方案,权限组的概念
网络请求缓存处理,okhttp 如何处理网络缓存的
图片加载库相关,bitmap 如何处理大图,如一张 30M 的大图,如何预防 OOM
进程保活
listview 图片加载错乱的原理和解决方案
https 相关,如何验证证书的合法性,https 中哪里用了对称加密,哪里用了非对称加密,对加密算法(如 RSA)等是否有了解
阿里巴巴
LRUCache 原理
图片加载原理
模块化实现(好处,缘由)
视频加密传输
统计启动时长,标准
如何保持应用的稳定性
ThreadLocal 原理
谈谈 classloader
动态布局
热修复、插件化
HashMap 源码, SpareArray 原理
性能优化,怎么保证应用启动不卡顿
SP 是进程同步的吗?有什么方法作到同步
介绍下 SurfView
HashMap 实现原理,ConcurrentHashMap 的实现原理
BroadcastReceiver,LocalBroadcastReceiver 区别
Bundle 机制
Handler 机制
android 事件传递机制
线程间 操做 List
App启动流程,从点击桌面开始
动态加载
类加载器
OSGI
Https 请求慢的解决办法,DNS,携带数据,直接访问 IP
GC 回收策略
画出 Android 的大致架构图
描述清点击 Android Studio 的 build 按钮后发生了什么
大致说清一个应用程序安装到手机上时发生了什么;
对 Dalvik、ART 虚拟机有基本的了解;
Android 上的 Inter-Process-Communication 跨进程通讯时如何工做的;
App 是如何沙箱化,为何要这么作;
权限管理系统(底层的权限是如何进行 grant 的);
进程和 Application 的生命周期;
系统启动流程 Zygote 进程 –> SystemServer 进程 –> 各类系统服务 –> 应用进程
美团
线程挂起,休眠,释放资源相关,唤醒,线程同步,数据传递,问了不少线程的问题,问了 20 分钟大概
static synchronized 方法的多线程访问和做用,同一个类里面两个 synchronized 方法,两个线程同时访问的问题
内部类和静态内部类和匿名内部类,以及项目中的应用
泛型是什么以及在项目中的应用
handler 发消息给子线程,looper 怎么启动
down、move、up 事件的传递
activity 栈
封装 view 的时候怎么知道 view 的大小
intent-filter
arraylist 和 linkedlist 的区别,以及应用场景
怎么启动 service,service 和 activity 怎么进行数据交互
下拉状态栏是否是影响 activity 的生命周期,若是在 onStop 的时候作了网络请求,onResume 的时候怎么恢复
view 渲染
对于基础知识考察的比较多,注重原理,要求面试者在学习技术的时候加深理解。不一样的公司在业务侧重点方面有所不一样,但整体须要掌握的技能有:高级 UI、性能优化、移动架构等方面。
感谢你们能耐着性子,看完我啰哩啰嗦的文章。
我愿与各位坚守在Android开发岗位的同胞们互相交流学习,共同进步!
在这里我也分享一份本身收录整理的Android学习PDF+架构视频+面试文档+源码笔记,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料帮助你们学习提高进阶,也节省你们在网上搜索资料的时间来学习,也能够分享给身边好友一块儿学习
若是你有须要的话,能够点赞,关注我,而后关注微信公众号【Android开发之家】免费领取