最近在工作中处理了一些内存泄露的问题,在这个过程中我尤其发现了一些基本的问题反而忽略导致内存泄露,比如静态变量,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.close()将不会执行

  正确写法应该是:

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的时候会重新查询执行。

一般来说,也只是这种需求,很少需要看不到界面的时候还在不停地显示查询结果,如果真的有,不予讨论,记得最终关掉就OK了。

这个时候,我们一般可以在onStop()方法里面把cursor关掉(同时意味着你可能需要在onResume()或者onStart()重新查询一下)。

@Override
protected void onStop() {super.onStop();// mCursorAdapter会释放之前的cursor,相当于关闭了cursormCursorAdapter.changeCursor(null);
}

  我专门附上CursorAdapter的changeCursor()方法源码,让大家看的更清楚,免得不放心changeCursor(null)方法:

/*** Change the underlying cursor to a new cursor. If there is an existing cursor it will be* closed.** @param cursor The new cursor to be used*/
public void changeCursor(Cursor cursor) {Cursor old = swapCursor(cursor);if (old != null) {old.close();}
}/*** Swap in a new Cursor, returning the old Cursor.  Unlike* {@link #changeCursor(Cursor)}, the returned old Cursor is <em>not</em>* closed.** @param newCursor The new cursor to be used.* @return Returns the previously set Cursor, or null if there wasa not one.* If the given new Cursor is the same instance is the previously set* Cursor, null is also returned.*/
public Cursor swapCursor(Cursor newCursor) {if (newCursor == mCursor) {return null;}Cursor oldCursor = mCursor;if (oldCursor != null) {if (mChangeObserver != null) oldCursor.unregisterContentObserver(mChangeObserver);if (mDataSetObserver != null) oldCursor.unregisterDataSetObserver(mDataSetObserver);}mCursor = newCursor;if (newCursor != null) {if (mChangeObserver != null) newCursor.registerContentObserver(mChangeObserver);if (mDataSetObserver != null) newCursor.registerDataSetObserver(mDataSetObserver);mRowIDColumn = newCursor.getColumnIndexOrThrow("_id");mDataValid = true;// notify the observers about the new cursornotifyDataSetChanged();} else {mRowIDColumn = -1;mDataValid = false;// notify the observers about the lack of a data setnotifyDataSetInvalidated();}return oldCursor;
}

6. 实战AsyncQueryHandler中Cursor的关闭问题
    AsyncQueryHandler是一个很经典很典型的分析Cursor的例子,不仅一阵见血,能举一反三,而且非常常见,为以后避免。
    AsyncQueryHandler文档参考地址:
    http://developer.android.com/reference/android/content/AsyncQueryHandler.html
    下面这段代码是Android2.3系统中Mms信息主页面ConversationList源码的一部分,大家看看Cursor正确关闭了吗?

转载自:https://blog.csdn.net/love_xiaozhao/article/details/52243308

Cursor的关闭问题相关推荐

  1. Android编程之另一种原因造成Cursor未关闭错误

    关于异常错误:Finalizing a Cursor that has not been deactivated or closed.如果有朋友也遇到了类似的错误,又不是因为cursor没有关闭造成的 ...

  2. Context.managedQuery()和context.getContentResolver()获取Cursor关闭注意事项

    在获取图片缩略图时,获取游标并进行相关的操作. Cursor cursor = context.getContentResolver().query(MediaStore.Images.Thumbna ...

  3. Oracle 游标(cursor) 说明

    一.  Cursor说明 Oracle里的cursor分为两种:一种是shared cursor,一种是session cursor. 1.1 Shared cursor 说明 sharedcurso ...

  4. oracle的cursor的介绍

    oracle的cursor的介绍 一  概念      游标是SQL的一个内存工作区,由系统或用户以变量的形式定义. 游标的作用就是用于临时存储从数据库中提取的数据块.在某些情况下,需要把数据从存放在 ...

  5. Oracle中Cursor介绍

    一  概念 游标是SQL的一个内存工作区,由系统或用户以变量的形式定义.游标的作用就是用于临时存储从数据库中提取的数据块.在某些情况下,需要把数据从 存放在磁盘的表中调到计算机内存中进行处理,最后将处 ...

  6. Android数据库Cursor异常原因和Fd泄露分析

    前言 手机应用和Android终端机应用不同的地方是:Android终端机应用长时间运行,必须保证长时间(几周到几个月不等)稳定运行,不崩溃,而手机应用经常进出,很难发现一些问题.线下监控内存泄漏可以 ...

  7. 4.pymysql .cursor属性方法(tcy)

    游标对象  2019/1/24 就是对数据库进行具体的操作了,比如增.删.改.查等等一系列操作都可以完成 1.游标类型: 类型 描述 Cursor 普通的游标对象,默认创建的游标对象 SSCursor ...

  8. Oracle中游标Cursor介绍

    转自:http://zohan.group.iteye.com/group/wiki/2278-cursor Oracle中游标Cursor介绍 一  概念 游标是SQL的一个内存工作区,由系统或用户 ...

  9. Oracle中游标(Cursor)介绍和使用

    一  概念  游标是SQL的一个内存工作区,由系统或用户以变量的形式定义.游标的作用就是用于临时存储从数据库中提取的数据块.在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理,最后将处 ...

  10. Oracle中cursor的介绍和使用,以及自己对cursor的理解

    一,概念         Oracle的游标是一个指向上下文区域的指针,这个上下文区域是PL/SQL语句块中在执行SELECT语句或DML数据操纵语句时分配的.比如当使用SELECT语句查询返回多行数 ...

最新文章

  1. R语言使用scales包的hue_pal函数获取ggplot2任何级别的离散色码、使用scales包的hue_pal函数获取ggplot2任何级别的反序(reverse)离散色码
  2. Struts2中的链接标签 s:url和s:a
  3. 1. VIM 系列 - 简单入门,拾起兴趣
  4. java修饰类的关键字_JAVA中的修饰关键字
  5. centOS安装Mysql指南
  6. linux输出文件没有找到,Linux环境下标准输入、输出、错误信息详解
  7. 一文详解MySQL中的事件调度器EVENT
  8. 关于CMR和SMR技术硬盘的选择
  9. PostgreSQL是否区分大小写
  10. 【PIL】Image中blend的简单使用
  11. SpringBoot整合调用微信模板方法实现微信公众号消息通知推送,Java实现微信公众号给关注用户推送自定义消息通知(手把手从0到1)
  12. html的method属性,HTML中的form标签的method属性怎么用?这里有method属性的用法介绍...
  13. 用python画卡通人物的画法_教你绘制扁平化风格的卡通人物肖像
  14. 理解elasticsearch
  15. CodeForces - 1646E Power Board (思维,数学)
  16. python—生产者消费者模型
  17. 多线程爬虫爬取电影天堂资源
  18. iphone开发小记
  19. 8086段地址为什么是16的倍数?
  20. 第一章 SRE与DevOps之间的联系

热门文章

  1. java autorun_玩转Autorun.inf
  2. 解决transition与fadeIn,fadeOut冲突问题
  3. 2019牛客暑期多校训练营(第八场) Explorer (线段树分治+区间离散化)
  4. Android知识点深究
  5. options.add_argument(r'--user-data-dir=C:\Users\name\AppData\Local\Google\Chrome\User Data') 绕过登录
  6. Android EditText 只能输入数字
  7. 一文看懂ARM Cortex-M处理器 ARM Cortex-M 处理器家族介绍和比较
  8. 青龙脚本之-饿了么脚本
  9. 第三周助教工作总结——NWNU李泓毅
  10. 关于 IOS 的299$ 美元企业模式(In House)及Installing Apps Wirelessly 详解