EntityGenerator:生成实体类
一、网络底层框架设计
优化:
1. 工具类的优化
2. 网络底层的优化
onFail统一处理
dialog
progressbar统一处理
3.数据缓存设计
设置缓存时间
cookie设置
二、图片缓存设计
1.imageloader的实现原理
内存---硬盘----网络
2.Fresco
把程序中显示网络图片的ImageView替换为SimpleDraweeView,添加fresco命名空间
缓存设计:
(1)Bitmap缓存
位于java的堆中
三、网络流量优化
1.通信层面
gzip压缩
新数据传输协议:ProtoBuffer(二进制格式)
减少网络发送请求次数
页面跳转时,如未请求完成要终止,基类中提供一个cancelrequest方法,清空网络请求队列
2.图片策略优化
(1)准备几套不同分辨率的图,在请求时额外加上width和height
(2)服务器按比例压缩图片
(3)imageType属性
(4)低流量模式,按照请求网络类型传参数
3.如何防止重复发送网络请求
HTTP header中加入max-age,这样某个固定的时间内都将返回empty body,当然这个方法是死的,把时间完全限制了,这个方法回掉也会同样要执行多次。
还有个晕招,就是直接设置按钮的clickable为false,或者使用progressbar,类似于楼主的方法,比如点赞的场景。
使用Map的话,在回掉的时候,还是需要回收HashMap的,维护Map还不如只维护一个boolean呢。
Volley中如果开了缓存的话, 相同的请求同时只会有一个去真正的请求, 后续都走缓存, 虽然不会请求多次, 但是回调是会执行多次的, 和这个需求不match
内存泄漏问题
资源对象没有关闭造成,如查询数据库没有关闭游标
构造Adapter时,没有使用缓存ConvertView
Bitmap对象在不使用时调用recycle()释放内存
context逃逸问题
注册没有取消,如动态注册广播在Activity销毁前没有unregisterReceiver
集合对象未清理,如无用时没有释放对象的引用
在Activity中使用非静态的内部类,并开启一个长时间运行的线程,因为内部类持有Activity的引用,会导致Activity本来可以被gc时却长期得不到回收
哪些情况下发生OOM
类的静态变量持有大数据对象 静态变量长期维持到大数据对象的引用,阻止垃圾回收。
非静态内部类存在静态实例 非静态内部类会维持一个到外部类实例的引用,如果非静态内部类的实例是静态的,就会间接长期维持着外部类的引用,阻止被回收掉。
资源对象未关闭 资源性对象比如(Cursor,File文件等)往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们, 以便它们的缓冲及时回收内存。它们的缓冲不仅存在于java虚拟机内,还存在于java虚拟机外。 如果我们仅仅是把它的引用设置为null,而不关闭它们,往往会造成内存泄露。 解决办法: 比如SQLiteCursor(在析构函数finalize(),如果我们没有关闭它,它自己会调close()关闭), 如果我们没有关闭它,系统在回收它时也会关闭它,但是这样的效率太低了。 因此对于资源性对象在不使用的时候,应该调用它的close()函数,将其关闭掉,然后才置为null. 在我们的程序退出时一定要确保我们的资源性对象已经关闭。 程序中经常会进行查询数据库的操作,但是经常会有使用完毕Cursor后没有关闭的情况。如果我们的查询结果集比较小, 对内存的消耗不容易被发现,只有在常时间大量操作的情况下才会复现内存问题,这样就会给以后的测试和问题排查带来困难和风险,记得try catch后,在finally方法中关闭连接
Handler内存泄漏 Handler作为内部类存在于Activity中,但是Handler生命周期与Activity生命周期往往并不是相同的,比如当Handler对象有Message在排队,则无法释放,进而导致本该释放的Acitivity也没有办法进行回收。 解决办法:
声明handler为static类,这样内部类就不再持有外部类的引用了,就不会阻塞Activity的释放
如果内部类实在需要用到外部类的对象,可在其内部声明一个弱引用引用外部类
一些不良代码习惯 有些代码并不造成内存泄露,但是他们的资源没有得到重用,频繁的申请内存和销毁内存,消耗CPU资源的同时,也引起内存抖动 解决方案 如果需要频繁的申请内存对象和和释放对象,可以考虑使用对象池来增加对象的复用。 例如ListView便是采用这种思想,通过复用converview来避免频繁的GC
Dalvik虚拟机和JVM有什么区别
Dalvik 基于寄存器,而 JVM 基于栈。基于寄存器的虚拟机对于更大的程序来说,在它们编译的时候,花费的时间更短。
Dalvik执行.dex格式的字节码,而JVM执行.class格式的字节码
四、ANR原因及定位分析
UI线程响应超时:被阻塞或者耗时太长
KeyDispatchTimeout View的按键事件或者触摸事件在5s内无法得到响应
BroadcastTimeout 广播的onreceive()运行在主线程中,10s内无法完成处理
ServiceTimeout service的生命周期在20s内无法完成处理
NetWorkOnMainThreadException
动画
等待子线程释放锁
结合logcat日志和位于手机内部存储的/data/anr/traces.txt
避免与检测:
1.StrictMode 严格模式 检测线程策略 setThreadPolicy
及虚拟机策略 setVmPoicy
oncreate()中初始化
2.BlockCanary 性能监控函数库,利用主线程的消息循环机制,通过对比时间点判断是否超时
LeakCanary
oncreate()中初始化
一、网络底层框架设计
优化:
1. 工具类的优化
2. 网络底层的优化
onFail统一处理
dialog
progressbar统一处理
3.数据缓存设计
设置缓存时间
cookie设置
二、图片缓存设计
1.imageloader的实现原理
内存---硬盘----网络
2.Fresco
把程序中显示网络图片的ImageView替换为SimpleDraweeView,添加fresco命名空间
缓存设计:
(1)Bitmap缓存
位于java的堆中
三、网络流量优化
1.通信层面
gzip压缩
新数据传输协议:ProtoBuffer(二进制格式)
减少网络发送请求次数
页面跳转时,如未请求完成要终止,基类中提供一个cancelrequest方法,清空网络请求队列
2.图片策略优化
(1)准备几套不同分辨率的图,在请求时额外加上width和height
(2)服务器按比例压缩图片
(3)imageType属性
(4)低流量模式,按照请求网络类型传参数
3.如何防止重复发送网络请求
HTTP header中加入max-age,这样某个固定的时间内都将返回empty body,当然这个方法是死的,把时间完全限制了,这个方法回掉也会同样要执行多次。
还有个晕招,就是直接设置按钮的clickable为false,或者使用progressbar,类似于楼主的方法,比如点赞的场景。
使用Map的话,在回掉的时候,还是需要回收HashMap的,维护Map还不如只维护一个boolean呢。
Volley中如果开了缓存的话, 相同的请求同时只会有一个去真正的请求, 后续都走缓存, 虽然不会请求多次, 但是回调是会执行多次的, 和这个需求不match
内存泄漏问题
资源对象没有关闭造成,如查询数据库没有关闭游标
构造Adapter时,没有使用缓存ConvertView
Bitmap对象在不使用时调用recycle()释放内存
context逃逸问题
注册没有取消,如动态注册广播在Activity销毁前没有unregisterReceiver
集合对象未清理,如无用时没有释放对象的引用
在Activity中使用非静态的内部类,并开启一个长时间运行的线程,因为内部类持有Activity的引用,会导致Activity本来可以被gc时却长期得不到回收
哪些情况下发生OOM
类的静态变量持有大数据对象 静态变量长期维持到大数据对象的引用,阻止垃圾回收。
非静态内部类存在静态实例 非静态内部类会维持一个到外部类实例的引用,如果非静态内部类的实例是静态的,就会间接长期维持着外部类的引用,阻止被回收掉。
资源对象未关闭 资源性对象比如(Cursor,File文件等)往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们, 以便它们的缓冲及时回收内存。它们的缓冲不仅存在于java虚拟机内,还存在于java虚拟机外。 如果我们仅仅是把它的引用设置为null,而不关闭它们,往往会造成内存泄露。 解决办法: 比如SQLiteCursor(在析构函数finalize(),如果我们没有关闭它,它自己会调close()关闭), 如果我们没有关闭它,系统在回收它时也会关闭它,但是这样的效率太低了。 因此对于资源性对象在不使用的时候,应该调用它的close()函数,将其关闭掉,然后才置为null. 在我们的程序退出时一定要确保我们的资源性对象已经关闭。 程序中经常会进行查询数据库的操作,但是经常会有使用完毕Cursor后没有关闭的情况。如果我们的查询结果集比较小, 对内存的消耗不容易被发现,只有在常时间大量操作的情况下才会复现内存问题,这样就会给以后的测试和问题排查带来困难和风险,记得try catch后,在finally方法中关闭连接
Handler内存泄漏 Handler作为内部类存在于Activity中,但是Handler生命周期与Activity生命周期往往并不是相同的,比如当Handler对象有Message在排队,则无法释放,进而导致本该释放的Acitivity也没有办法进行回收。 解决办法:
声明handler为static类,这样内部类就不再持有外部类的引用了,就不会阻塞Activity的释放
如果内部类实在需要用到外部类的对象,可在其内部声明一个弱引用引用外部类
一些不良代码习惯 有些代码并不造成内存泄露,但是他们的资源没有得到重用,频繁的申请内存和销毁内存,消耗CPU资源的同时,也引起内存抖动 解决方案 如果需要频繁的申请内存对象和和释放对象,可以考虑使用对象池来增加对象的复用。 例如ListView便是采用这种思想,通过复用converview来避免频繁的GC
Dalvik虚拟机和JVM有什么区别
Dalvik 基于寄存器,而 JVM 基于栈。基于寄存器的虚拟机对于更大的程序来说,在它们编译的时候,花费的时间更短。
Dalvik执行.dex格式的字节码,而JVM执行.class格式的字节码
四、ANR原因及定位分析
UI线程响应超时:被阻塞或者耗时太长
KeyDispatchTimeout View的按键事件或者触摸事件在5s内无法得到响应
BroadcastTimeout 广播的onreceive()运行在主线程中,10s内无法完成处理
ServiceTimeout service的生命周期在20s内无法完成处理
NetWorkOnMainThreadException
动画
等待子线程释放锁
结合logcat日志和位于手机内部存储的/data/anr/traces.txt
避免与检测:
1.StrictMode 严格模式 检测线程策略 setThreadPolicy
及虚拟机策略 setVmPoicy
oncreate()中初始化
2.BlockCanary 性能监控函数库,利用主线程的消息循环机制,通过对比时间点判断是否超时
LeakCanary
oncreate()中初始化