概述
1、 查询内存情况
:通过Android Studio的Memory Monitor查看内存中Dalvik Heap的实时变化
2、 异常出现的情况
:当之前分配的内存+新分配的内存超出系统分配的内存时即 getMemoryClass()获取到的内存数据时就超出了内存,出现OOM
3、 异常出现的原因
:1、无限循环;
2、加载的图片过大或者图片过多;
3、无限制创建各种对象;
4、等
4、 异常处理方法
:1、减少对象的使用,尽量使用轻量级的(使用更加轻量的数据结构、少使用静态与枚举等)
2、使用图片是可进行压缩(大小、质量压缩),使用3级缓存机制,使用LRU的机制来缓存处理好的Bitmap图片,减少内存的付出
3、listview与gridview、recyclerview等加载数据时,使用convertView进行复用。
4、一些系统自带的资源,尽量使用系统的,可以减小内存,也能减小apk的大小。
知识点:LRU机制
计算机中有一个概念,我们用缓存来存放以前读取的数据,而不是直接丢掉,这样,再次读取的时候,可以直接在缓存里面取,而不用再重新查找一遍,这样系统的反应能力会有很大提高。但是,当我们读取的个数特别大的时候,我们不可能把所有已经读取的数据都放在缓存里,毕竟内存大小是一定的,我们一般把最近常读取的放在缓存里(相当于我们把最近联系的朋友的姓名和电话放在大脑里一样)。现在,我们就来研究这样一种缓存机制。
LRU缓存利用了这样的一种思想。LRU是Least Recently Used 的缩写,翻译过来就是“最近最少使用”,也就是说,LRU缓存把最近最少使用的数据移除,让给最新读取的数据。而往往最常读取的,也是读取次数最多的,所以,利用LRU缓存,我们能够提高系统的performance.
实现:
要实现LRU缓存,我们首先要用到一个类 LinkedHashMap。 用这个类有两大好处:一是它本身已经实现了按照访问顺序的存储,也就是说,最近读取的会放在最前面,最最不常读取的会放在最后(当然,它也可以实现按照插入顺序存储)。第二,LinkedHashMap本身有一个方法用于判断是否需要移除最不常读取的数,
其中实现方式可使用双链表 + hashtable来实现
1.
public class LRUCache {
2.
3.
private int cacheSize;
4.
private Hashtable<Object, Entry> nodes;//缓存容器
5.
private int currentSize;
6.
private Entry first;//链表头
7.
private Entry last;//链表尾
8.
9.
public LRUCache(int i) {
10.
currentSize = 0;
11.
cacheSize = i;
12.
nodes = new Hashtable<Object, Entry>(i);//缓存容器
13.
}
14.
15.
/**
16.
* 获取缓存中对象,并把它放在最前面
17.
*/
18.
public Entry get(Object key) {
19.
Entry node = nodes.get(key);
20.
if (node != null) {
21.
moveToHead(node);
22.
return node;
23.
} else {
24.
return null;
25.
}
26.
}
27.
28.
/**
29.
* 添加 entry到hashtable, 并把entry
30.
*/
31.
public void put(Object key, Object value) {
32.
//先查看hashtable是否存在该entry, 如果存在,则只更新其value
33.
Entry node = nodes.get(key);
34.
35.
if (node == null) {
36.
//缓存容器是否已经超过大小.
37.
if (currentSize >= cacheSize) {
38.
nodes.remove(last.key);
39.
removeLast();
40.
} else {
41.
currentSize++;
42.
}
43.
node = new Entry();
44.
}
45.
node.value = value;
46.
//将最新使用的节点放到链表头,表示最新使用的.
47.
moveToHead(node);
48.
nodes.put(key, node);
49.
}
50.
51.
/**
52.
* 将entry删除, 注意:删除操作只有在cache满了才会被执行
53.
*/
54.
public void remove(Object key) {
55.
Entry node = nodes.get(key);
56.
//在链表中删除
57.
if (node != null) {
58.
if (node.prev != null) {
59.
node.prev.next = node.next;
60.
}
61.
if (node.next != null) {
62.
node.next.prev = node.prev;
63.
}
64.
if (last == node)
65.
last = node.prev;
66.
if (first == node)
67.
first = node.next;
68.
}
69.
//在hashtable中删除
70.
nodes.remove(key);
71.
}
72.
73.
/**
74.
* 删除链表尾部节点,即使用最后 使用的entry
75.
*/
76.
private void removeLast() {
77.
//链表尾不为空,则将链表尾指向null. 删除连表尾(删除最少使用的缓存对象)
78.
if (last != null) {
79.
if (last.prev != null)
80.
last.prev.next = null;
81.
else
82.
first = null;
83.
last = last.prev;
84.
}
85.
}
86.
87.
/**
88.
* 移动到链表头,表示这个节点是最新使用过的
89.
*/
90.
private void moveToHead(Entry node) {
91.
if (node == first)
92.
return;
93.
if (node.prev != null)
94.
node.prev.next = node.next;
95.
if (node.next != null)
96.
node.next.prev = node.prev;
97.
if (last == node)
98.
last = node.prev;
99.
if (first != null) {
100.
node.next = first;
101.
first.prev = node;
102.
}
103.
first = node;
104.
node.prev = null;
105.
if (last == null)
106.
last = first;
107.
}
108.
/*
109.
* 清空缓存
110.
*/
111.
public void clear() {
112.
first = null;
113.
last = null;
114.
currentSize = 0;
115.
}
116.
117.
}
118.
119.
class Entry {
120.
Entry prev;//前一节点
121.
Entry next;//后一节点
122.
Object value;//值
123.
Object key;//键
124.
}
最后
以上就是落后绿茶为你收集整理的基础知识记录:OOM异常出现的情况与处理方式的全部内容,希望文章能够帮你解决基础知识记录:OOM异常出现的情况与处理方式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复