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的时候会重新查询执行。
一般来说,也只是这种需求,很少需要看不到界面的时候还在不停地显示查询结果,如果真的有,不予讨论,记得最终关掉就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的关闭问题相关推荐
- Android编程之另一种原因造成Cursor未关闭错误
关于异常错误:Finalizing a Cursor that has not been deactivated or closed.如果有朋友也遇到了类似的错误,又不是因为cursor没有关闭造成的 ...
- Context.managedQuery()和context.getContentResolver()获取Cursor关闭注意事项
在获取图片缩略图时,获取游标并进行相关的操作. Cursor cursor = context.getContentResolver().query(MediaStore.Images.Thumbna ...
- Oracle 游标(cursor) 说明
一. Cursor说明 Oracle里的cursor分为两种:一种是shared cursor,一种是session cursor. 1.1 Shared cursor 说明 sharedcurso ...
- oracle的cursor的介绍
oracle的cursor的介绍 一 概念 游标是SQL的一个内存工作区,由系统或用户以变量的形式定义. 游标的作用就是用于临时存储从数据库中提取的数据块.在某些情况下,需要把数据从存放在 ...
- Oracle中Cursor介绍
一 概念 游标是SQL的一个内存工作区,由系统或用户以变量的形式定义.游标的作用就是用于临时存储从数据库中提取的数据块.在某些情况下,需要把数据从 存放在磁盘的表中调到计算机内存中进行处理,最后将处 ...
- Android数据库Cursor异常原因和Fd泄露分析
前言 手机应用和Android终端机应用不同的地方是:Android终端机应用长时间运行,必须保证长时间(几周到几个月不等)稳定运行,不崩溃,而手机应用经常进出,很难发现一些问题.线下监控内存泄漏可以 ...
- 4.pymysql .cursor属性方法(tcy)
游标对象 2019/1/24 就是对数据库进行具体的操作了,比如增.删.改.查等等一系列操作都可以完成 1.游标类型: 类型 描述 Cursor 普通的游标对象,默认创建的游标对象 SSCursor ...
- Oracle中游标Cursor介绍
转自:http://zohan.group.iteye.com/group/wiki/2278-cursor Oracle中游标Cursor介绍 一 概念 游标是SQL的一个内存工作区,由系统或用户 ...
- Oracle中游标(Cursor)介绍和使用
一 概念 游标是SQL的一个内存工作区,由系统或用户以变量的形式定义.游标的作用就是用于临时存储从数据库中提取的数据块.在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理,最后将处 ...
- Oracle中cursor的介绍和使用,以及自己对cursor的理解
一,概念 Oracle的游标是一个指向上下文区域的指针,这个上下文区域是PL/SQL语句块中在执行SELECT语句或DML数据操纵语句时分配的.比如当使用SELECT语句查询返回多行数 ...
最新文章
- R语言使用scales包的hue_pal函数获取ggplot2任何级别的离散色码、使用scales包的hue_pal函数获取ggplot2任何级别的反序(reverse)离散色码
- Struts2中的链接标签 s:url和s:a
- 1. VIM 系列 - 简单入门,拾起兴趣
- java修饰类的关键字_JAVA中的修饰关键字
- centOS安装Mysql指南
- linux输出文件没有找到,Linux环境下标准输入、输出、错误信息详解
- 一文详解MySQL中的事件调度器EVENT
- 关于CMR和SMR技术硬盘的选择
- PostgreSQL是否区分大小写
- 【PIL】Image中blend的简单使用
- SpringBoot整合调用微信模板方法实现微信公众号消息通知推送,Java实现微信公众号给关注用户推送自定义消息通知(手把手从0到1)
- html的method属性,HTML中的form标签的method属性怎么用?这里有method属性的用法介绍...
- 用python画卡通人物的画法_教你绘制扁平化风格的卡通人物肖像
- 理解elasticsearch
- CodeForces - 1646E Power Board (思维,数学)
- python—生产者消费者模型
- 多线程爬虫爬取电影天堂资源
- iphone开发小记
- 8086段地址为什么是16的倍数?
- 第一章 SRE与DevOps之间的联系
热门文章
- java autorun_玩转Autorun.inf
- 解决transition与fadeIn,fadeOut冲突问题
- 2019牛客暑期多校训练营(第八场) 	Explorer (线段树分治+区间离散化)
- Android知识点深究
- options.add_argument(r'--user-data-dir=C:\Users\name\AppData\Local\Google\Chrome\User Data') 绕过登录
- Android EditText 只能输入数字
- 一文看懂ARM Cortex-M处理器 ARM Cortex-M 处理器家族介绍和比较
- 青龙脚本之-饿了么脚本
- 第三周助教工作总结——NWNU李泓毅
- 关于 IOS 的299$ 美元企业模式(In House)及Installing Apps Wirelessly 详解