Search code examples
androidlistviewandroid-contentproviderandroid-contentresolver

Content Provider ListView wrong id on Update or Delete


This method populates data from a different app's content provider into the listview, my problem is in the onItemClick, I believe the method's 'long id' returns a wrong id, sometimes it gets decremented every time I delete an entry, and since that's the case, whenever I attempt to delete or update a row, most of the time it would produce an error(CursorIndexOutOfBounds), but there are instances where in it would update or delete a different row.

private void populateList(){
        arNames = new ArrayList<String>();
        String name;
        Cursor cursor = getContentResolver().query(PATH_URI, null, null, null, null);
        cursor.moveToFirst();
        do{
            name = cursor.getString(cursor.getColumnIndex("FULL"));
            arNames.add(name);
        }while(cursor.moveToNext());
        cursor.close();
        final CustomAdapter customAdapter = new CustomAdapter(inflater, arNames);
        listNames.setAdapter(customAdapter);
        listNames.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        listNames.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Cursor c = getContentResolver().query(PATH_URI, null, "_id=" + id, null, null);
                c.moveToFirst();
                view.setBackgroundColor(Color.GRAY);

                cNames[coupler] = c.getString(c.getColumnIndex("FULL"));
                Toast.makeText(getApplicationContext(),cNames[coupler],Toast.LENGTH_LONG).show();
                if (cNames[0].equals(cNames[1]) && coupler == 1) {
                    showEditor(id);
                } else if (coupler++ == 1) {
                    coupler = 0;
                    populateList();
                    Toast.makeText(getApplication(), flameOn(cNames[0], cNames[1]), Toast.LENGTH_LONG).show();
                }
            }
        });
    }

12-17 16:31:52.075    3852-3852/com.example.den.flamesclient E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.den.flamesclient, PID: 3852
    android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
            at android.database.AbstractCursor.checkPosition(AbstractCursor.java:426)
            at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
            at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
            at android.database.CursorWrapper.getString(CursorWrapper.java:114)
            at com.example.den.flamesclient.MainActivity$1.onItemClick(MainActivity.java:71)
            at android.widget.AdapterView.performItemClick(AdapterView.java:299)
            at android.widget.AbsListView.performItemClick(AbsListView.java:1113)
            at android.widget.AbsListView$PerformClick.run(AbsListView.java:2904)
            at android.widget.AbsListView.onTouchUp(AbsListView.java:3650)
            at android.widget.AbsListView.onTouchEvent(AbsListView.java:3429)
            at android.view.View.dispatchTouchEvent(View.java:7706)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2210)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1945)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2068)
            at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1515)
            at android.app.Activity.dispatchTouchEvent(Activity.java:2458)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2016)
            at android.view.View.dispatchPointerEvent(View.java:7886)
            at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3954)
            at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3833)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3399)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3449)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3418)
            at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3525)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3426)
            at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3582)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3399)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3449)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3418)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3426)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3399)
            at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5602)
            at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5582)
            at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5553)
            at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5682)
            at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
            at android.os.MessageQueue.nativePollOnce(Native Method)
            at android.os.MessageQueue.next(MessageQueue.java:138)
            at android.os.Looper.loop(Looper.java:123)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)

Solution

  • I have found the reason why my row id was giving the wrong ID. Well I wouldn't really call it 'wrong' after realizing what the bug was.

    You see when a cursor queries data and project them in a listview, they don't actually query those data that has been deleted. My mistake was I had forgotten that dbId would not be restructured if a delete statement had been executed, the id would remain as is which in our case would remain fixed, while its' neighboring columns would be deleted.

    listNames.setOnItemClickListener(new AdapterView.OnItemClickListener()
                    Cursor c = getContentResolver().query(PATH_URI, null, "_id=" + id, null, null);
    

    The snippet above is where I went wrong. I was comparing the listview id (more likely the item position on the list view) and a content provider db id.

    What I did was to compare a different row, more specifically a String from both my db and what is projected on my ListView, I had first set my arraylist(arNames) global. Then this:

    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Cursor c = getContentResolver().query(PATH_URI, null, "COLUMN_NAME= '" + arNames.get(position) + "'", null, null);