近来发现一个关于SQLiteCursor的问题,多线程操作下产生的异常,偶现。
在Application中操作了Cursor的close()后紧接着又从DBHelper中取了新的引用。然后发广播,到Activity的Receiver中接受后,调用了app.getCursor();取得Application中的Cursor引用,调用了cursor.getCount();
结果出现了一个NullPointer错误:
E/AndroidRuntime(28116): java.lang.NullPointerException E/AndroidRuntime(28116): at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:144) E/AndroidRuntime(28116): at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133) E/AndroidRuntime(28116): at com.letv.signalsourcemanager.MainActivity.handleScanCompleted(MainActivity.java:1728) E/AndroidRuntime(28116): at com.letv.signalsourcemanager.MainActivity.access$1200(MainActivity.java:88) E/AndroidRuntime(28116): at com.letv.signalsourcemanager.MainActivity$10.onReceive(MainActivity.java:2570) E/AndroidRuntime(28116): at android.support.v4.content.LocalBroadcastManager.executePendingBroadcasts(LocalBroadcastManager.java:297) E/AndroidRuntime(28116): at android.support.v4.content.LocalBroadcastManager.access$000(LocalBroadcastManager.java:46) E/AndroidRuntime(28116): at android.support.v4.content.LocalBroadcastManager$1.handleMessage(LocalBroadcastManager.java:116) E/AndroidRuntime(28116): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime(28116): at android.os.Looper.loop(Looper.java:137) E/AndroidRuntime(28116): at android.app.ActivityThread.main(ActivityThread.java:4777) E/AndroidRuntime(28116): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime(28116): at java.lang.reflect.Method.invoke(Method.java:511) E/AndroidRuntime(28116): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789) E/AndroidRuntime(28116): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556) E/AndroidRuntime(28116): at dalvik.system.NativeStart.main(Native Method) W/ActivityManager( 635): Force finishing activity com.letv.signalsourcemanager/.MainActivity
查看SQLiteCursor源码发现,
@Override public int getCount() { if (mCount == NO_COUNT) { fillWindow(0); } return mCount; } private void fillWindow(int requiredPos) { clearOrCreateWindow(getDatabase().getPath()); if (mCount == NO_COUNT) { int startPos = DatabaseUtils.cursorPickFillWindowStartPosition(requiredPos, 0); mCount = mQuery.fillWindow(mWindow, startPos, requiredPos, true); mCursorWindowCapacity = mWindow.getNumRows(); if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "received count(*) from native_fill_window: " + mCount); } } else { int startPos = DatabaseUtils.cursorPickFillWindowStartPosition(requiredPos, mCursorWindowCapacity); mQuery.fillWindow(mWindow, startPos, requiredPos, false); } }
具体是getCount的时候现判断
mCount == NO_COUNT
实际上此时cursor的count是大于0的,然后进入了fillWindow,然后在
mCursorWindowCapacity = mWindow.getNumRows();
出现了空指针错误。
由于现象是偶现的,所以我就判定跟多线程有关,导致Cursor的问题。
那么就需要加同步锁来解决了。具体方式有很多,此处不赘述。
相关推荐
以下是对Android SQLite3多线程操作问题的深入研究和总结: 1. **getWriteableDatabase()与getReadableDatabase()的区别** - `getWriteableDatabase()` 是读写操作的入口,它会尝试打开一个可读写的数据库连接。...
2. 错误处理:处理网络异常、文件写入异常等,确保程序在异常情况下能够恢复或给出错误提示。 3. 进度保存:定期保存下载进度,防止进程被杀死后丢失进度信息。 4. 用户体验:合理设计下载界面,提供暂停、取消、重...
在Pro*C编程中,线程安全是一个至关重要的概念,特别是在多线程环境下处理数据库操作时。Pro*C,Oracle的预编译C语言接口,允许开发者使用C语言编写PL/SQL代码,这为数据库访问提供了便利。然而,如果不正确地处理...
3. **线程安全**:`Cursor`实现了`java.lang.AutoCloseable`,可以使用try-with-resources语句,确保资源的正确释放。 缺点: 1. **不支持随机访问**:由于`Cursor`是顺序访问的,无法像List那样随机访问某个位置的...
在实际项目中,你可能还需要考虑线程安全、异常处理以及更复杂的查询逻辑。`MyStudent.apk`文件是一个Android应用的安装包,包含了上述操作的实现,可以通过反编译工具查看其源代码以获取更多细节。对于源码和工具的...
通常我们需要重写`onQueryComplete()`方法,这个方法会在查询完成后被调用,参数包括token、游标(Cursor)和异常信息。 ```java @Override protected void onQueryComplete(int token, Object cookie, Cursor ...
多线程在Python中可以通过`threading`模块实现,创建`Thread`对象并调用`start()`方法启动线程。 登录功能通常涉及用户输入验证,可能包括用户名和密码的校验。在Python中,这可以通过接收用户输入,然后与预设的...
`dup2_x2`可能指的是某种重复或倍增的操作,这可能是在测试某个功能的多线程处理或者复制行为。在Android测试中,我们经常使用JUnit和 Espresso等工具来编写单元测试和UI测试。这个类可能包含了针对特定业务逻辑或...
在Android开发中,SQLite是一个非常重要的组成部分,它是一个轻量级的数据库系统,适用于移动设备。SQLite被广泛用于存储和管理应用...记住,实际应用中还需要处理异常,优化查询性能,并考虑多线程环境下的安全性。
PyMySQL还提供了其他高级特性,如连接池管理、支持多线程等。这些功能可以帮助开发者更高效地管理和使用数据库资源。 总结,PyMySQL是Python与MySQL数据库交互的重要工具,其易用性和强大的功能使其成为Python...
在C#编程中,自定义动画鼠标是一种提升用户体验和视觉效果的技术。...通过学习和研究这个源码,开发者不仅可以掌握自定义鼠标指针的技术,还能加深对Windows Forms事件处理和多线程编程的理解,提升自己的C#编程技能。
10. **并发处理**:OTL支持多线程编程,可以安全地在多线程环境中访问数据库。 在实际使用中,首先需要将`otlv4.h`头文件包含进C++源代码,然后根据需求实例化相关的类,进行数据库连接、SQL执行、数据读写等操作。...
2. **线程安全**:PySQLPool设计为线程安全,这意味着在多线程环境下,多个线程可以同时使用连接池中的连接,而不会出现资源竞争的问题。 3. **资源管理**:连接池可以设置最大连接数量,防止过多连接导致数据库...
- Loader是异步加载数据的框架,常与Cursor结合使用,能在后台线程中执行查询,提高用户体验。 7. Android编程实践: - 使用RecyclerView展示日记列表,提供良好的滚动性能和内存管理。 - 响应用户交互,如点击...
4. **线程安全(Thread Safety)**:DBUtils 考虑到了多线程环境下的安全问题,确保了每个线程都有独立的数据库连接,避免了线程间的资源竞争。 5. **兼容性**:DBUtils 可以与遵循 Python DB-API 2.0 规范的任何...
为了在多线程环境下安全遍历集合,应使用`Collections.synchronizedCollection()`或`CopyOnWriteArrayList`等线程安全的集合,或者在遍历过程中使用`synchronized`关键字进行同步控制。 总的来说,迭代器是Java中...
在Android平台上,获取和...在实际开发中,可能还需要结合用户界面、线程管理、异常处理等多方面知识,以实现完整且健壮的短信功能。在SMSTest项目中,你可能能看到具体的实现示例,这有助于进一步理解和实践这些概念。
在Android开发中,数据操作是应用的基本功能之...这只是一个基础框架,实际项目中可能需要考虑更多因素,如异常处理、数据持久化、多线程操作等。在学习过程中,不断实践和优化,才能更好地掌握Android数据操作的精髓。