Android 岗常见 40 道面试题,面试前必须了解的知识点!,android 开发工程师企业所在区域
内存泄露就是指该被 GC 垃圾回收的,但被一个生命周期比它长的对象仍然在引用它,导致无法回收,造成内存泄露,过多的内存泄露会导致 OOM。
27.什么情况导致内存泄漏?
1)非静态内部类、匿名内部类:非静态内部类、匿名内部类 都会持有外部类的一个引用,如果有一个静态变量引用了非静态内部类或者匿名内部类,导致非静态内部类或者匿名内部类的生命周期比外部类(Activity)长,就会导致外部类在该被回收的时候,无法被回收掉,引起内存泄露, 除非外部类被卸载。
解决办法:将非静态内部类、匿名内部类 改成静态内部类,或者直接抽离成一个外部类。 如果在静态内部类中,需要引用外部类对象,那么可以将这个引用封装在一个 WeakReference 中。
2)静态的 View:当一个 Activity 经常启动,但是对应的 View 读取非常耗时,我们可以通过静态 View 变量来保持对该 Activity 的 rootView 引用。这样就可以不用每次启动 Activity 都去读取并渲染 View 了。但 View attach 到我们的 Window 上,就会持有一个 Context(即 Activity)的引用。而我们的 View 有事一个静态变量,所以导致 Activity 不被回收。
解决办法: 在使用静态 View 时,需要确保在资源回收时,将静态 View detach 掉。
3)Handler:在 Activity 中定义 Handler 对象,那么 Handler 持有 Activty 的引用。而每个 Message 对象是持有 Handler 的引用的(Message 对象的 target 属性持有 Handler 引用),从而导致 Message 间接引用到了 Activity。如果在 Activty destroy 之后,消息队列中还有 Message 对象,Activty 是不会被回收的。
解决办法: 将 Handler 放入单独的类或者将 Handler 放入到静态内部类中(静态内部类不会持有外部类的引用)。如果想要在 handler 内部去调用所在的外部类 Activity,可以在 handler 内部使用弱引用的方式指向所在 Activity,在 onDestory 时,调用相应的方法移除回调和删除消息。
4)监听器(各种需要注册的 Listener,Watcher 等):当我们需要使用系统服务时,比如执行某些后台任务、为硬件访问提供接口等等系统服务。我们需要把自己注册到服务的监听器中。然而,这会让服务持有 activity 的引用,如果程序员忘记在 activity 销毁时取消注册,那就会导致 activity 泄漏了。
解决办法:在 onDestory 中移除注册
5)资源对象没关闭造成内存泄漏:当我们打开资源时,一般都会使用缓存。比如读写文件资源、打开数据库资源、使用 Bitmap 资源等等。当我们不再使用时,应该关闭它们,使得缓存内存区域及时回收。
解决办法:使用 try finally 结合,在 try 块中打开资源,在 finally 中关闭资源
6)属性动画:在使用 ValueAnimator 或者 ObjectAnimator 时,如果没有及时做 cancel 取消动画,就可能造成内存泄露。因为在 cancel 方法里,最后调用了 endAnimation(); ,在 endAnimation 里,有个 AnimationHandler 的单例,会持有属性动画对象的引用。
解决办法:在 onDestory 中调用动画的 cancel 方法
7)RxJava:在使用 RxJava 时,如果在发布了一个订阅后,由于没有及时取消,导致 Activity/Fragment 无法销毁,导致的内存泄露。
解决办法:使用 RxLifeCycle
28.内存泄漏和内存溢出区别?
(1)内存泄漏
1)内存泄漏:指程序中已动态分配的堆内存由于某种原因未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统奔溃等严重后果。
2)一次内存泄漏似乎不会有大的影响,但内存泄漏后堆积的结果就是内存溢出。
3)内存泄漏具有隐蔽性,积累性的特征,比其他内存非法访问错误更难检测。这是因为内存泄漏产生的原因是内存块未被释放,属于遗漏型缺陷而不是过错型缺陷。此外,内存泄漏不会直接产生可观察的错误,而是逐渐积累,降低系统的整体性性能。
4)如何有效的进行内存分配和释放,防止内存泄漏,是软件开发人员的关键问题,比如一个服务器应用软件要长时间服务多个客户端,若存在内存泄漏,则会逐渐堆积,导致一系列严重后果。
(2)内存溢出
指程序在申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储 int 类型数据的存储空间,但是你却存储 long 类型的数据,就会导致内存不够用,报错 OOM,即出现内存溢出的错误。
LruCache 默认缓存大小
(4MB)
30.ContentProvider 的权限管理(解答:读写分离,权限控制-精确到表级,URL 控制)
31.如何通过广播拦截和 abort 一条短信?
32.广播是否可以请求网络?
33.广播引起 anr 的时间限制是多少?
34.计算一个 view 的嵌套层级
35.Activity 栈
36.Android 线程有没有上限?
37.线程池有没有上限?
38.ListView 重用的是什么?
39.Android 为什么引入 Parcelable?
40.有没有尝试简化 Parcelable 的使用?
总结
--
在工作中有不少朋友联系我,问我有没有相关推荐的书或者资料可以学习的。
自己也在不断的学习和提升,所以再这些过程中吧遇到的面试题整理成了一份 983 页的 PDF,需要这份完整文档的伙伴可以私信我【666】获取或点击查看更多详情~
评论