一、内存泄露
1.1、上下文导致内存泄露
在 android程序开发 中,内存泄漏问题是比较常见的问题,相信有过一些android编程经历的程序猿都遇到过各种各样的内存泄漏。
内存泄漏是造成应用程序OOM的主要原因之一,是编程中必须避免的问题。
1、对于生命周期比Activity长的对象,如果需要应该使用ApplicationContext ;
2、在涉及到Context时先考虑ApplicationContext,当然它并不是万能的,对于Application,Service,Activity三者的Context的应用场景如下:
中:**NO1表示Application和Service可以启动一个Activity,不过需要创建一个新的task任务队列。而对于Dialog而言,只有在Activity中才能创建。
3、对于需要在静态内部类中使用非静态外部成员变量(如:Context、View ),可以在静态内部类中使用弱引用来引用外部类的变量来避免内存泄漏 。
4、对于生命周期比Activity长的内部类对象,并且内部类中使用了外部类的成员变量,可以这样做避免内存泄漏:
a)将内部类改为静态内部类
b)静态内部类中使用弱引用来引用外部类的成员变量
5、对于不再需要使用的对象,显示的将其赋值为null,比如使用完Bitmap后先调用recycle(),再赋为null 。
6、保持对对象生命周期的敏感,特别注意单例、静态对象、全局性集合等的生命周期。
对于上方创建新的任务队列进行解释,比如服务中开启Activity则需要开启新任务队列:
Intent dialogIntent = new Intent(getBaseContext(), YourActivity.class); dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); getApplication().startActivity(dialogIntent);
1.2、查询数据库未关闭Cursor
在Android中,Cursor是很常用的对象,但在写代码时,经常会有人忘记关闭,或因代码逻辑问题状态导致close未被调用到。
通常,在Activity中,我们可以调用StartManagingCursor或直接使用manageQuery让Activity自动管理Cursor对象。
若操作Cursor代码和UI不同步,则没必要先判断Activity是否结束,或在调用onDestory前,先等待后台线程结束。除此之外,以下也是比较常见的Cursor未关闭的情况。
try { Cursor c = queryCursor(); int a = c.getInt(1); ...... c.close(); } catch (Exception e) { }
表面看起来,Cursor.close()已经被调用,如果出现异常则有可能跳过close(),从而导致内存泄露。正确的写法如下:
Cursor c = queryCursor(); try { int a = c.getInt(1); ...... } catch (Exception e) { } finally { c.close(); //在finally中调用close(), 保证其一定会被调用 }
1.3、调用registerReceiver后未调用unregisterReceiver()
在调用registReceiver后,若未调用unregisterReceiver,所占内存是相当大的。
registerReceiver(new BroadcastReceiver() { ... }, filter); ...
这个错误很严重,会导致BroadcastReceiver不会被unregist而导致内存泄露。因为匿名类获取不到引用来取消注册。
1.4、Bitmap使用后未调用recycle()
根据SDK的描述,调用recycle并非是必须的,但是实际使用中,Bitmap占用内存是非常大的,所以不再使用时,尽量调用recycle()释放资源,以及置顶空。
mBitmap.recycle(); mBitmap = null;
1.5、未关闭InputStream/OutputStream
在使用文件或者访问网络资源时,使用InputStream/OutputStream时,未关闭资源或未及时释放也会导致内存泄露。