做android 开发的经常会遇android.database.CursorWindowAllocationException这样子的错误;一般出现这样的错误,大部分原因是因为没有关闭cursor,或者是因为Cursor使用不当,之前我的遇到这样的代码:
ForecastData situation = null; ................ Cursor cursor = mContext.getContentResolver().query(WEATHER_URI, null, null, null, null); try { if (cursor != null && cursor.moveToFirst()) { ........... cursor.close(); } } catch (Exception e) { e.printStackTrace(); } finally { if (cursor != null) { cursor.close(); } } return situation; }
初看一下没有什么问题,但如果Cursor cursor = mContext.getContentResolver().query这里返回的错误还是会有可能造成程序的未关闭Cursor,因此我们改成标准写法:
Cursor cursor = null; try { cursor = getContentResolver().query(URI, .....);// 1 //dosomething } finally { if (cursor != null) { cursor.close();// 2 } }
这样改了之后,运行了很多个版本都一直没有问题。直到有一天一个同事发现可能查询数据库比较耗时。因此把方法放到线程里面去执行,而已每次查询的时候都会创建一个线程。没有想到上面代码又出错误了,如果您稍不留意不会怀疑这块代码的问题,因为try-finally写法不存在逻辑上的问题。由于这里未考虑到多线程场景,try-finally并不能保证query打开游标在dosomething时,被其他线程再次调用query打开游标。所以当遇到存在多线程的调用时必须对游标打开到关闭时间段添加锁,即这里是对try-finally块加锁。
下面简单解释一下:
假设:线程A执行到1处创建了一个Cursor,然后dosomething比较耗时........
线程B又来查询数据库,因此到1处又创建一个Cursor,此时如果AB执行完,就会关闭锁,看起来没有问题,但由于是同一个对象,所以AB关闭的cursor都是B创建的,因此
A创建的Cursor就没有关闭!
时间: 2024-10-15 06:42:31