基础知识记录:OOM异常出现的情况与处理方式

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.    }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值