javaandroidstaleobjectstatestaledataexception

Why is my ListView method throwing a 'Stale object state' exception?


Currently within my app I am getting a stale object exception when I call a method that updates a ListView from my database.

I have been careful to close all of my cursors when querying my database, I also manage my cursor when it is returned through the use of 'startManagingCursor' but still I get this issue.

At the moment, when I add a new item to my database, I recall a ListView update method within a private method of my class. This is where the object is throwing the exception.

I have read of people 'refreshing' the session, and also I believe database versions come into this? But overall I'm stuck and cant solve this.

Updated error:

02-13 13:23:06.588: E/AndroidRuntime(287): FATAL EXCEPTION: main 02-13 13:23:06.588: E/AndroidRuntime(287): android.database.StaleDataException: Access closed cursor 02-13 13:23:06.588: E/AndroidRuntime(287): at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:217) 02-13 13:23:06.588: E/AndroidRuntime(287): at android.database.AbstractWindowedCursor.getInt(AbstractWindowedCursor.java:84) 02-13 13:23:06.588: E/AndroidRuntime(287): at com.example.flybase2.ShoppingList.updateTotal(ShoppingList.java:248) 02-13 13:23:06.588: E/AndroidRuntime(287): at com.example.flybase2.ShoppingList.access$1(ShoppingList.java:231) 02-13 13:23:06.588: E/AndroidRuntime(287): at com.example.flybase2.ShoppingList$2.onClick(ShoppingList.java:350) 02-13 13:23:06.588: E/AndroidRuntime(287): at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:158) 02-13 13:23:06.588: E/AndroidRuntime(287): at android.os.Handler.dispatchMessage(Handler.java:99) 02-13 13:23:06.588: E/AndroidRuntime(287): at android.os.Looper.loop(Looper.java:123) 02-13 13:23:06.588: E/AndroidRuntime(287): at android.app.ActivityThread.main(ActivityThread.java:4627) 02-13 13:23:06.588: E/AndroidRuntime(287): at java.lang.reflect.Method.invokeNative(Native Method) 02-13 13:23:06.588: E/AndroidRuntime(287): at java.lang.reflect.Method.invoke(Method.java:521) 02-13 13:23:06.588: E/AndroidRuntime(287): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 02-13 13:23:06.588: E/AndroidRuntime(287): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 02-13 13:23:06.588: E/AndroidRuntime(287): at dalvik.system.NativeStart.main(Native Method)

This is my class that calls the ListView:

package com.example.flybase2;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.DialogInterface;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.widget.SimpleCursorAdapter;
import android.text.Editable;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

public class ShoppingList extends ListActivity implements OnClickListener {

Button AddItem;
ListView showItems;
SimpleCursorAdapter cursorAdapter;
Long itemId;
EditText totalPrice;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.shoppinglistlayout);


    AddItem = (Button) findViewById(R.id.btnAddItem);

    showItems = (ListView)findViewById(android.R.id.list);

    totalPrice = (EditText)findViewById(R.id.totalListPrice);

    AddItem.setOnClickListener(this);

    setList();

}
    ERROR**********************************8
@Override
public void onClick(View clickedAdd) {



    show();

}

@Override
protected void onListItemClick(ListView l, View v, int position, long idd) {
    super.onListItemClick(l, v, position, idd);

     itemId = idd;

final CharSequence[] items = {"Edit Item", "Delete Item", "Show Most Purchased Item"};

    Builder alertDialogBuilder = new AlertDialog.Builder(ShoppingList.this);

    alertDialogBuilder.setTitle("Item Options:");



    alertDialogBuilder.setItems(items, new DialogInterface.OnClickListener() {

        public void onClick(DialogInterface dialog, int item) {

            if (items[item].equals("Edit Item")) {

                AlertDialog.Builder builder = new AlertDialog.Builder(ShoppingList.this);

                builder.setTitle("Edit Item");


                DBHandlerShop setEdit = new DBHandlerShop(ShoppingList.this, null, null);

                setEdit.open();
                String itemName = setEdit.getItem(itemId);
                int itemAmount = setEdit.getItemQuan(itemId);
                int itemPrice = setEdit.getItemCost(itemId);
                setEdit.close();
                                    LinearLayout layout = new LinearLayout(ShoppingList.this);
                                    layout.setOrientation(LinearLayout.VERTICAL);

                                    final EditText titleBox = new EditText(ShoppingList.this);
                                    titleBox.setText(itemName);
                                    titleBox.setHint("Item Name:");
                                    layout.addView(titleBox);

                                    final EditText quantityBox = new EditText(ShoppingList.this);
                                    quantityBox.setText(Integer.toString(itemAmount));
                                    quantityBox.setHint("Item Quantity");
                                    layout.addView(quantityBox);

                                    final EditText priceBox = new EditText(ShoppingList.this);
                                    priceBox.setText(Integer.toString(itemPrice));
                                    priceBox.setHint("Item Price.");
                                    layout.addView(priceBox);

                                    builder.setView(layout);



                                    builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int whichButton) {


                                        Editable valueItem = titleBox.getText();
                                        Editable valueAmount = quantityBox.getText();
                                    Editable valuePrice = priceBox.getText();

                                   String itemDescription = valueItem.toString();
                                    String s = valueAmount.toString();
                                    int itemAmount = Integer.parseInt(s);
                                    String a = valuePrice.toString();
                                    int itemPrice = Integer.parseInt(a);
                                    try{
                                                DBHandlerShop update = new DBHandlerShop(ShoppingList.this, null, null);
                                                update.open();
                                                update.updateItem(itemId, itemDescription, itemAmount, itemPrice);
                                                update.close();
                                    }
                                    catch(Exception e)
                                    {
                                        Dialog e1 = new Dialog(ShoppingList.this);
                                        e1.setTitle("Item unsuccesfully updated");
                                        TextView txt = new TextView(ShoppingList.this);
                                        txt.setText("Success");
                                        e1.setContentView(txt);
                                        e1.show();
                                    }
                                    finally
                                    {
                                        Dialog e1 = new Dialog(ShoppingList.this);
                                        e1.setTitle("Item succesfully updated");
                                        TextView txt = new TextView(ShoppingList.this);
                                        txt.setText("Success");
                                        e1.setContentView(txt);
                                        e1.show();

                                        setList();

                                    int cost = updateTotal();
                                        totalPrice.setText(cost);
                                    }


                                      }


                                    });

                                    builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                                      public void onClick(DialogInterface dialog, int whichButton) {

                                      }
                                    });

                                    builder.show();


            }

            else if (items[item].equals("Delete Item")) 
            {

                   DBHandlerShop delete = new DBHandlerShop(ShoppingList.this,null, null);

                   delete.open();
                   delete.deleteItem(itemId);
                   delete.close();

                   setList();

            }

            else if (items[item].equals("Show Most Purchased Item")) 
            {

            }

            }  

        });

    alertDialogBuilder.show();

}


private void setList() {

    DBHandlerShop DBShop = new DBHandlerShop(this, null, null);

    DBHandlerShop searchItems = new DBHandlerShop(this, null, null);

    searchItems.open();

    Cursor cursor = searchItems.getItems();

    startManagingCursor(cursor);

    String [] from = new String [] {DBShop.KEY_ITEMSHOP, DBShop.KEY_ITEMNUM, DBShop.KEY_ITEMPRICE};
    int [] to = new int [] {R.id.txtSetItem, R.id.txtSetAmount, R.id.txtSetPrice};

    cursorAdapter = new SimpleCursorAdapter(this, R.layout.setshoppinglist, cursor, from, to);
    showItems.setAdapter(cursorAdapter);


}


private int updateTotal() {


    DBHandlerShop total = new DBHandlerShop(this, null, null);

    int totalPrice = 0;
    total.open();
    Cursor totalPrices = total.getTotals();
    total.close();

     if (totalPrices != null) {

         startManagingCursor(totalPrices);
         if (totalPrices.moveToFirst()) {


             do {
                 int cost = totalPrices.getInt(3);
                 totalPrice += cost;

             } while (totalPrices.moveToNext());

             return totalPrice;
         }

     }

    return 0;


}

private void show()
{

    AlertDialog.Builder builder = new AlertDialog.Builder(ShoppingList.this);

        builder.setTitle("Enter Item Details:");

                            LinearLayout layout = new LinearLayout(this);
                            layout.setOrientation(LinearLayout.VERTICAL);

                            final EditText titleBox = new EditText(this);

                            titleBox.setHint("Item Name:");
                            layout.addView(titleBox);

                            final EditText quantityBox = new EditText(this);

                            quantityBox.setHint("Item Quantity");
                            layout.addView(quantityBox);

                            final EditText priceBox = new EditText(this);

                            priceBox.setHint("Item Price.");
                            layout.addView(priceBox);

                            builder.setView(layout);



                            builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int whichButton) {
                            try
                            {

                                Editable valueItem = titleBox.getText();
                                Editable valueAmount = quantityBox.getText();
                            Editable valuePrice = priceBox.getText();


                                String itemDescription = valueItem.toString();
                                String s = valueAmount.toString();
                                int itemAmount = Integer.parseInt(s);
                                String a = valuePrice.toString();
                                int itemPrice = Integer.parseInt(a);




                            DBHandlerShop addItem = new DBHandlerShop(ShoppingList.this, null, null);
                            addItem.open();
                            addItem.insertItems(itemDescription, itemAmount, itemPrice);
                            addItem.close();


                            }
                            catch(Exception e)
                            {
                            Dialog e1 = new Dialog(ShoppingList.this);
                            e1.setTitle("Item unsuccesfully added");
                            TextView txt = new TextView(ShoppingList.this);
                            txt.setText("Success");
                            e1.setContentView(txt);
                            e1.show();

                            }
                            finally
                            {
                                Dialog e = new Dialog(ShoppingList.this);
                            e.setTitle("Item succesfully added.");
                            TextView txt = new TextView(ShoppingList.this);
                            txt.setText("Success");
                            e.setContentView(txt);
                            e.show();

                        setList();

                    int cost = updateTotal();
                        totalPrice.setText(cost);

                            }


                              }

                            });

                            builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                              public void onClick(DialogInterface dialog, int whichButton) {

                              }
                            });

                            builder.show();

}
}

This is the cursor returned from the database:

    public Cursor getItems() {


        String [] columns = new String[]{KEY_ROWSHOPID, KEY_ITEMSHOP, KEY_ITEMNUM, KEY_ITEMPRICE};
        Cursor c = ourDatabase.query(DATABASE_TABLESHOP, columns, null, null, null, null, null);
         if(c != null && c.getCount() > 0)
        {
        c.moveToFirst();
        c.close();
        return c;
        }
        c.close();
        return null;
    }

Solution

  • 02-13 11:37:52.013: E/AndroidRuntime(287): android.database.StaleDataException: Access closed cursor

    Your problem is that you are trying to access data on closed Cursor. This is not allowed so remove line with c.close() and now it should works.

    Note: Generally is recommended to close any cursors, datasources in onPause() or onDestroy() methods.

    Update: Here is edited method, copy and paste and try it again. It should works.

    public Cursor getItems() {
       String [] columns = new String[] {KEY_ROWSHOPID, KEY_ITEMSHOP, KEY_ITEMNUM, 
                                         KEY_ITEMPRICE};
       Cursor c = ourDatabase.query(DATABASE_TABLESHOP, columns, null, null, null,
                                    null, null);
       if (c.moveToFirst()) {
          return c;
       }
       return null;
    }
    
    
    public void onDestroy() {
       super.onDestroy();
       closeSources();
    }
    
    private void closeSources() {
       if (c != null) {
          c.close();
       }
       if (db != null) {
          db.close();
       }
    }