但是 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操作,则这两个的效果就完全一样了。