2、发生ANR的条件
应用程序的响应性是由ActivityManager和WindowManager系统服务监视的,当ANR发生条件满足时,就会弹出ANR的对话框
- Activity超过5秒无响应
- BroadcastReceiver超过10秒无响应
- Service超过20秒无响应
3、造成ANR的主要原因
主线程被IO操作阻塞
- Activity的所有生命周期回调都是执行在主线程的
- Service默认执行在主线程中
- BoardcastReceiver的回调onReceive()执行在主线程中
- AsyncTask的回调除了doInBackground,其他都是在主线程中
- 没有使用子线程Looper的Handler的handlerMessage,post(Runnable)都是执行在主线程中
4、如何解决ANR
- 使用AsyncTask处理耗时IO操作
- 使用Thread或HandlerThread提供优先级
- 使用Handler处理工作线程的耗时操作
- Activity的onCreate和onResume回调尽量避免耗时操作
OOM面试题
1、什么是OOM
OOM指Out of memory(内存溢出),当前占用内存加上我们申请的内存资源超过了Dalvik虚拟机的最大内存限制就会抛出Out of memory异常
2、OOM相关概念
- 内存溢出:指程序在申请内存时,没有足够的空间供其使用
- 内存泄漏:指程序分配出去的内存不再使用,无法进行回收
- 内存抖动:指程序短时间内大量创建对象,然后回收的现象
3、解决OOM
Bitmap相关
- 图片压缩
- 加载缩略图
- 在滚动时不加载图片
- 回收Bitmap
- 使用inBitmap属性
- 捕获异常
其他相关
- listview重用convertView、使用lru
- 避免onDraw方法执行对象的创建
- 谨慎使用多进程
Bitmap面试题
1、recycle
- 在安卓3.0以前Bitmap是存放在堆中的,我们只要回收堆内存即可
- 在安卓3.0以后Bitmap是存放在内存中的,我们需要回收native层和Java层的内存
- 官方建议我们3.0以后使用recycle方法进行回收,该方法也可以不主动调用,因为垃圾回收器会自动收集不可用的Bitmap对象进行回收
- recycle方法会判断Bitmap在不可用的情况下,将发送指令到垃圾回收器,让其回收native层和Java层的内存,则Bitmap进入dead状态
- recycle方法是不可逆的,如果再次调用getPixels()等方法,则获取不到想要的结果
2、LruCache原理
LruCache是个泛型类,内部采用LinkedHashMap来实现缓存机制,它提供get方法和put方法来获取缓存和添加缓存,其最重要的方法trimToSize是用来移除最少使用的缓存和使用最久的缓存,并添加最新的缓存到队列中
UI卡顿面试题
1、UI卡顿原理
View的绘制帧数保持60fps是最佳,这要求每帧的绘制时间不超过16ms(1000/60),如果安卓不能在16ms内完成界面的渲染,那么就会出现卡顿现象
2、UI卡顿的原因分析
- 在UI线程中做轻微的耗时操作,导致UI线程卡顿
- 布局Layout过于复杂,无法在16ms内完成渲染
- 同一时间动画执行的次数过多,导致CPU和GPU负载过重
- overDraw,导致像素在同一帧的时间内被绘制多次,使CPU和GPU负载过重
- View频繁的触发measure、layout,导致measure、layout累计耗时过多和整个View频繁的重新渲染
- 频繁的触发GC操作导致线程暂停,会使得安卓系统在16ms内无法完成绘制
- 冗余资源及逻辑等导致加载和执行缓慢
- ANR
3、UI卡顿的优化
- 布局优化
- 使用include、ViewStub、merge
- 不要出现过于嵌套和冗余的布局
- 使用自定义View取代复杂的View
- ListView优化
- 复用convertView
- 滑动不加载
- 背景和图片优化
- 缩略图
- 图片压缩
- 避免ANR
- 不要在UI线程中做耗时操作
内存泄漏面试题
1、Java内存泄漏引起的主要原因
长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄漏
2、Java内存分配策略
- 静态存储区:又称方法区,主要存储全局变量和静态变量,在整个程序运行期间都存在
- 栈区:方法体的局部变量会在栈区创建空间,并在方法执行结束后会自动释放变量的空间和内存
- 堆区:保存动态产生的数据,如:new出来的对象和数组,在不使用的时候由Java回收器自动回收
3、Android解决内存泄漏的例子
- 单例造成的内存泄漏:在单例中,使用context.getApplicationContext()作为单例的context
- 匿名内部类造成的内存泄漏:由于非静态内部类持有匿名外部类的引用,必须将内部类设置为static
- Handler造成的内存泄漏:使用static的Handler内部类,同时在实现内部类中持有Context的弱引用
- 避免使用static变量:由于static变量会跟Activity生命周期一致,当Activity退出后台被后台回收时,static变量是不安全,所以也要管理好static变量的生命周期
- 资源未关闭造成的内存泄漏:比如Socket、Broadcast、Cursor、Bitmap、ListView等,使用完后要关闭
- AsyncTask造成的内存泄漏:由于非静态内部类持有匿名内部类的引用而造成内存泄漏,可以通过AsyncTask内部持有外部Activity的弱引用同时改为静态内部类或在onDestroy()中执行AsyncTask.cancel()进行修复
内存管理面试题
1、Android内存管理机制
- 分配机制
- 管理机制
2、内存管理机制的特点
- 更少的占用内存
- 在合适的时候,合理的释放系统资源
- 在系统内存紧张的时候,能释放掉大部分不重要的资源
- 能合理的在特殊生命周期中,保存或还原重要数据
3、内存优化方法
- Service完成任务后应停止它,或用IntentService(因为可以自动停止服务)代替Service
- 在UI不可见的时候,释放其UI资源
- 在系统内存紧张的时候,尽可能多的释放非重要资源
- 避免滥用Bitmap导致内存浪费
- 避免使用依赖注入框架
- 使用针对内存优化过的数据容器
- 使用ZIP对齐的APK
- 使用多进程
冷启动和热启动面试题
1、什么是冷启动和热启动
- 冷启动:在启动应用前,系统中没有该应用的任何进程信息
- 热启动:在启动应用时,在已有的进程上启动应用(用户使用返回键退出应用,然后马上又重新启动应用)
2、冷启动和热启动的区别
- 冷启动:创建Application后再创建和初始化MainActivity
- 热启动:创建和初始化MainActivity即可
3、冷启动时间的计算
这个时间值从应用启动(创建进程)开始计算,到完成视图的第一次绘制为止
4、冷启动流程
- Zygote进程中fork创建出一个新的进程
- 创建和初始化Application类、创建MainActivity
- inflate布局、当onCreate/onStart/onResume方法都走完
- contentView的measure/layout/draw显示在界面上
总结:Application构造方法->attachBaseContext()->onCreate()->Activity构造方法->onCreate()->配置主题中背景等属性->onStart()->onResume()->测量布局绘制显示在界面上
5、冷启动优化
- 减少第一个界面onCreate()方法的工作量
- 不要让Application参与业务的操作
- 不要在Application进行耗时操作
- 不要以静态变量的方式在Application中保存数据
- 减少布局的复杂性和深度
- 不要在mainThread中加载资源
- 通过懒加载方式初始化第三方SDK
其他优化面试题
1、Android不用静态变量存储数据
- 静态变量等数据由于进程已经被杀死而被初始化
- 使用其他数据传输方式:文件/sp/contentProvider
2、SharePreference安全问题
- 不能跨进程同步
- 文件不宜过大
3、内存对象序列化
- Serializeble:是java的序列化方式,Serializeble在序列化的时候会产生大量的临时对象,从而引起频繁的GC
- Parcelable:是Android的序列化方式,且性能比Serializeble高,Parcelable不能使用在要将数据存储在硬盘上的情况
4、避免在UI线程中做繁重的操作
架构模式面试题
插件化面试题
1、插件化解决的问题
- 动态加载APK(反射、类加载器)
- 资源加载(反射、AssetManager、独立资源、分段资源)
- 代码加载(反射获取生命周期)
2、类加载器(Java中字节码添加到虚拟机中)
- DexClassLoader:能够加载未安装的jar/apk/dex,主要用于动态加载和代码热更新
- PathClassLoader:只能加载系统中已经安装过的apk
热更新面试题
1、热更新主要流程
- 线上检查到Crash
- 拉出Bugfix分支修复Crash问题
- jenkins构建和补丁生成
- app通过推送或主动拉取补丁文件
- 将Bugfix代码合到master上
2、热更新主流框架
- Dexposed
- AndFix
- Nuwa
- Tinker
分享读者
作者2013年java转到Android开发,在小厂待过,也去过华为,OPPO等大厂待过,18年四月份进了阿里一直到现在。
被人面试过,也面试过很多人。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长,而且极易碰到天花板技术停滞不前!
我们整理了一份阿里P7级别的Android架构师全套学习资料,特别适合有3-5年以上经验的小伙伴深入学习提升。
主要包括腾讯,以及字节跳动,阿里,华为,小米,等一线互联网公司主流架构技术。如果你有需要,尽管拿走好了。
如果你觉得自己学习效率低,缺乏正确的指导,可以点击加入资源丰富,学习氛围浓厚的技术圈一起学习交流吧!
群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。
35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。