Android App调试内存泄露之调试内存泄露之Cursor篇篇
最近在工作中处理了一些内存泄露的问题,在这个过程中我尤其发现了一些基本的问题反而忽略导致内存泄露,比如静态变
量,cursor关闭,线程,定时器,反注册,bitmap等等,我稍微统计并总结了一下,当然了,这些问题这么说起来比较笼统,
接下来我会根据问题,把一些实例代码贴出来,一步一步分析,在具体的场景下,用行之有效的方法,找出泄露的根本原因,
并给出解决方案。
现在,就从cursor关闭的问题开始把,谁都知道cursor要关闭,但是往往相反,人们却常常忘记关闭,因为真正的应用场景可
能并非理想化的简单。
1.理想化的理想化的cursor关闭关闭
代码如下:
// Sample Code
Cursor cursor = db.query();
List<String> list = convertToList(cursor);
cursor.close();
这是最简单的cursor使用场景,如果这里的cursor没有关闭,我想可能会引起万千口水,一片骂声。
但是实际场景可能并非如此,这里的cursor可能不会关闭,至少有以下两种可能。
2. Cursor未关闭的可能未关闭的可能
(1). cursor.close()之前发生异常。
(2). cursor需要继续使用,不能马上关闭,后面忘记关闭了。
3. Cursor.close()之前发生异常之前发生异常
这个很容易理解,应该也是初学者最开始碰到的常见问题,举例如下:
代码如下:
try {
Cursor c = queryCursor();
int a = c.getInt(1);
……
// 如果出错,后面的cursor.close()将不会执行
……
c.close();
} catch (Exception e) {
}
正确写法应该是:
代码如下:
Cursor c;
try {
c = queryCursor();
int a = c.getInt(1);
……
// 如果出错,后面的cursor.close()将不会执行
//c.close();
} catch (Exception e) {
} finally{
if (c != null) {
c.close();
}
}
很简单,但是需要时刻谨记。
4. Cursor需要继续使用,不能马上关闭需要继续使用,不能马上关闭
有没有这种情况?怎么办?
答案是有,CursorAdapter就是一个典型的例子。
CursorAdapter示例如下:
代码如下:
mCursor = getContentResolver().query(CONTENT_URI, PROJECTION,
null, null, null);
mAdapter = new MyCursorAdapter(this, R.layout.list_item, mCursor);
setListAdapter(mAdapter);
// 这里就不能关闭执行mCursor.close(),
// 否则list中将会无数据
5. 这样的这样的Cursor应该什么时候关闭呢?应该什么时候关闭呢?
这是个可以说好回答也可以说不好回答的问题,那就是在Cursor不再使用的时候关闭掉。
比如说,
上面的查询,如果每次进入或者resume的时候会重新查询执行。
一般来说,也是这种需求,很少我看不到界面的时候还在不停地显示查询结果吧,如果真的有,不予讨论,记得最终关掉就