造成oom的原因:OOM 常见原因及解决方案 - 简书 (jianshu.com):
- 内存泄漏、手机内存占用太高、一次读入太多数据
- 1、根据java的内存模型会出现内存溢出的内存有堆内存、方法区内存、虚拟机栈内存、native方法区内存;
- 2、一般说的OOM基本都是针对堆内存;
- 3、对于堆内存溢出主的根本原因有两种
(1)app进程内存达到上限
(2)手机可用内存不足,这种情况并不是我们app消耗了很多内存,而是整个手机内存不足
- 4、而我们需要解决的主要是app的内存达到上限
- 5、对于app内存达到上限只有两种情况
(1)申请内存的速度超出gc释放内存的速度
(2)内存出现泄漏,gc无法回收泄漏的内存,导致可用内存越来越少
- 6、对于申请内存速度超出gc释放内存的速度主要有2种情况
(1)往内存中加载超大文件
(2)循环创建大量对象
- 7、一般申请内存的速度超出gc释放内存基本不会出现,内存泄漏才是出现问题的关键所在
- 8、内存泄漏常见场景
(1)资源对象没关闭造成的内存泄漏(如: Cursor、File等)
(2)全局集合类强引用没清理造成的内存泄漏(特别是 static 修饰的集合)
(3)接收器、监听器注册没取消造成的内存泄漏,如广播,eventsbus
(4)Activity 的 Context 造成的泄漏,可以使用 ApplicationContext
(5)单例中的static成员间接或直接持有了activity的引用
(6)非静态内部类持有父类的引用,如非静态handler持有activity的引用
- 9、怎么对内存进行优化呢
三个方向
(1)为应用申请更大内存,把manifest上的largdgeheap设置为true
(2)减少内存的使用:
①使用优化后的集合对象,比如SpaseArray;
②使用微信的mmkv替代sharedpreference;
③对于经常打log的地方使用StringBuilder来组拼,替代String拼接
④统一带有缓存的基础库,特别是图片库,如果用了两套不一样的图片加载库就会出现2个图片各自维护一套图片缓存
⑤给ImageView设置合适尺寸的图片,列表页显示缩略图,查看大图显示原图
⑥优化业务架构设计,比如省市区数据分批加载,需要加载省就加载省,需要加载市就加载失去,避免一下子加载所有数据
(3)避免内存泄漏
编码规范上:
①资源对象用完一定要关闭,最好加finally
②静态集合对象用完要清理
③接收器、监听器使用时候注册和取消成对出现
④context使用注意生命周期,如果是静态类引用直接用ApplicationContext
⑤使用静态内部类
⑥结合业务场景,设置软引用,弱引用,确保对象可以在合适的时机回收
建设内存监控体系:
线下监控:
①使用ArtHook检测图片尺寸是否超出imageview自身宽高的2倍
②编码阶段Memery Profile看app的内存使用情况,是否存在内存抖动,内存泄漏,结合Mat分析内存泄漏
线上监控:
①上报app使用期间待机内存、重点模块内存、OOM率
②上报整体及重点模块的GC次数,GC时间
③使用LeakCannery自动化内存泄漏分析
-
10、真的出现低内存,设置一个兜底策略:
低内存状态回调,根据不同的内存等级做一些事情,比如在最严重的等级清空所有的bitmap,关掉所有界面,直接强制把app跳转到主界面,相当于app重新启动了一次一样,这样就避免了系统Kill应用进程,与其让系统kill进程还不如浪费一些用户体验,自己主动回收内存 -
AIDL机制:Android多进程
-
ListView和RecyclerView的区别有哪些:简书 - 写文章
- 滚动效果:RecycleView可以左右上下滚动、有多种布局方式;但是ListView只能上下滚动
- 动画效果上面有区别:RecycleView有动画,listView没有动画
- 点击事件的监听实现有区别:RecycleView没有实现控件的监听事件,但是ListView有
- 缓存机制:ListView只有两级复用机制,分为屏幕当前显示的和移除屏幕后不见的,移除屏幕的view会恢复为空白的view、变回刚创建时的状态态,等待下次调用绑定数据;RecycleView分为四级缓存,分为屏幕当前可见的缓存和两个移除屏幕的缓存,还有一个mViewCashExtension不研究:mCacheViews、mRecyclerPool,屏幕刚移除的viewHolder缓存到mCacheViews,但是在这里的ViewHolder还是屏幕可见时的状态,当mCacheViews中存不了时,将多余的ViewHolder转入mRecyclerPool,mRecyclerPool中的ViewHolder就恢复到了刚创建时的原始状态。
Bundle:四大组件间的进程间通信方式,简单易用,但传输的数据类型受限。文件共享
AIDL
文件共享: 不适合高并发场景,并且无法做到进程间的及时通信。
Messenger: 数据通过Message传输,只能传输Bundle支持的类型。Messenger
ContentProvider:android 系统提供的,简单易用,但使用受限,只能根据特定规则访问数据。
Socket:网络数据交换的常用方式。
广播接收者(Broadcast)的方式
- 线程通信方式:
针对原子性、可见性、加锁、java.util.concurrent包下的数据结构,
还有一个Android的hander机制
-
Android网络请求
-
如何实现深拷贝:
1、再次调用构造方法,再创建一个同样的对象
2、重写clone()方法:Object父类有个clone()的拷贝方法,不过它是protected类型的,我们需要重写它并修改为public类型。除此之外,子类还需要实现Cloneable接口来告诉JVM这个类是可以拷贝的:
public class Address implements Cloneable {
private String city;
private String country;
// constructors, getters and setters
@Override
public Address clone() throws CloneNotSupportedException {
return (Address) super.clone();
}
}
// 调用:
Address address = (Address ) super.clone();
-
hashSet才是用两个数组进行存储数据的;ArrayList是数组,LinkedList是链表
-
一个APP中创建多个进程的问题
网友评论