managedQuery 和 getContentResolver().query的区别
2016-01-27 16:34
435 查看
Activity 里面提供了一个 managedQuery() 方法,按照 Android SDK 里面的说明,“the activity will manage its lifecycle for you.” 听起来很好,Activity 可以替你管理 Cursor 的生命周期了,就不用记着去 close() 了,代码可以更简洁。
但是 Activity 是怎么去管理 Cursor 的生命周期的呢?SDK 文档没说。最近遇到一个 bug,在一个 Activity 中,用 managedQuery() 查询数据库,将查询得到的 Cursor 用 CursorAdapter 与 ListView 绑定。然后在 Activity 里面执行批量删除数据表记录操作,因为耗时比较长,所以用了多线程处理。测试团队发现的 bug 是,在删除操作进行过程中,如果按下 Home 键,应用就崩溃了。崩溃原因是
Cursor 被释放了,导致工作线程的删除操作异常。
看了 Activity.java 的源码之后就明白为什么会崩溃了。managedQuery() 其实无非就是把查询得到的 Cursor 放到了 Activity 类的一个数组成员变量中,然后当 Activity stop 的时候,将这个数组里的每个 cursor 都关掉,以及在 resume 的时候,将数组里的每个 cursor 都重新查询一次。所以在按下 Home 键之后,Activity 被 stop 了,cursor 也就被关闭了,如果有个线程还在继续使用这个
cursor,就会抛异常了。
因此,在用 managedQuery() 的时候,需要清楚 cursor 什么时候会被释放,并考虑好自己的代码在 cursor 被释放后不再需要使用这个 cursor.
而query 出自android.content.ContentResolver.query,其实managedQuery的内部实现是调用了query,只是在query的基础上,加上了startManagingCursor操作,以管理获取的cursor。因此,若是只用query,且对于query返回的cursor没有进行管理的话,会造成内存的泄露问题等等。但是若是用了query后,有对返回的cursor进行了startManagingCursor操作,则这两个的效果就完全一样了。
但是 Activity 是怎么去管理 Cursor 的生命周期的呢?SDK 文档没说。最近遇到一个 bug,在一个 Activity 中,用 managedQuery() 查询数据库,将查询得到的 Cursor 用 CursorAdapter 与 ListView 绑定。然后在 Activity 里面执行批量删除数据表记录操作,因为耗时比较长,所以用了多线程处理。测试团队发现的 bug 是,在删除操作进行过程中,如果按下 Home 键,应用就崩溃了。崩溃原因是
Cursor 被释放了,导致工作线程的删除操作异常。
看了 Activity.java 的源码之后就明白为什么会崩溃了。managedQuery() 其实无非就是把查询得到的 Cursor 放到了 Activity 类的一个数组成员变量中,然后当 Activity stop 的时候,将这个数组里的每个 cursor 都关掉,以及在 resume 的时候,将数组里的每个 cursor 都重新查询一次。所以在按下 Home 键之后,Activity 被 stop 了,cursor 也就被关闭了,如果有个线程还在继续使用这个
cursor,就会抛异常了。
因此,在用 managedQuery() 的时候,需要清楚 cursor 什么时候会被释放,并考虑好自己的代码在 cursor 被释放后不再需要使用这个 cursor.
而query 出自android.content.ContentResolver.query,其实managedQuery的内部实现是调用了query,只是在query的基础上,加上了startManagingCursor操作,以管理获取的cursor。因此,若是只用query,且对于query返回的cursor没有进行管理的话,会造成内存的泄露问题等等。但是若是用了query后,有对返回的cursor进行了startManagingCursor操作,则这两个的效果就完全一样了。
相关文章推荐
- JAVA基础笔记之StringBuilder和StringBuffer
- request.getRequestDispatcher()和response.sendRedirect()
- 错误400-The request sent by the client was syntactically incorrect
- mysql 5.5及以前版本的编码问题“Incorrect string value: '\xE6\x9B\xB9\xE5\x86\xAC...' for column 'realname' at row 1”
- Retrofit(2.0)入门小错误 -- Could not locate ResponseBody xxx Tried: * retrofit.BuiltInConverters
- Handler、Message、MessageQueue、Looper 理解
- 解决ntp的错误 no server suitable for synchronization found
- SPOJ QTREE - Query on a tree 【树链剖分】
- 实例详解Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(三)
- PB协议报错 it is missing required fields: (cannot determine missing fields for lite message)
- Juit3原理分析一(测试入门)
- UIMenuController,复制UILabel上的文字
- 使用UITabBarController创建Tabbar获取tabBarItem的点击方法
- UITabBarController和UINavigationController的整合使用
- Speeding up Gradle builds
- 交互设计的用户行为模式十二项 【转载】
- UITableViewCell中的bug
- Please specify exact device preset UUID
- build and install everything into local directory
- 给GPUImage录制的视频添加水印