Cursor多线程操作下的异常

       近来发现一个关于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的问题。

   那么就需要加同步锁来解决了。具体方式有很多,此处不赘述。

猜你喜欢

转载自dingran.iteye.com/blog/1909032