Varun Vishnoi
Varun Vishnoi

Reputation: 328

Close was never explicitly called on Database

I have a listview that is sourced by an sqlite db. I call fillData() at several different points to update the listview.

private void fillData() {
    readDatabase.open();
    Cursor itemsCursor = readDatabase.fetchAllItems();


    startManagingCursor(itemsCursor);

    String[] from = new String[] { DatabaseHandler.KEY_ITEM,
            DatabaseHandler.KEY_UNITCOST, DatabaseHandler.KEY_QUANTITY,
            DatabaseHandler.KEY_TOTAL };

    int[] to = new int[] { R.id.itemtext, R.id.costtext, R.id.quantitytext,
            R.id.totaltext };

    SimpleCursorAdapter items = new SimpleCursorAdapter(this,
            R.layout.rowincart, itemsCursor, from, to);

    setListAdapter(items);
    }

Whole code of class is added here

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setContentView(R.layout.cartactivity);
    readDatabase = new DatabaseHandler(this);
//  readDatabase.open();
    loadwidget();
    fillData();
    ListView lv = getListView();
    this.registerForContextMenu(lv);

}

private void loadwidget() {
    Bundle extras = getIntent().getExtras();
    cost = extras.getInt("Cost");
    quantity = extras.getInt("quantity");
    product = extras.getString("product");
    Log.i("Hello Testing", cost + " and " + quantity + "   " + product);

}

@SuppressWarnings("deprecation")
private void fillData() {
    readDatabase.open();
    itemsCursor = readDatabase.fetchAllItems();


    startManagingCursor(itemsCursor);

    String[] from = new String[] { DatabaseHandler.KEY_ITEM,
            DatabaseHandler.KEY_UNITCOST, DatabaseHandler.KEY_QUANTITY,
            DatabaseHandler.KEY_TOTAL };

    int[] to = new int[] { R.id.itemtext, R.id.costtext, R.id.quantitytext,
            R.id.totaltext };

    SimpleCursorAdapter items = new SimpleCursorAdapter(this,
            R.layout.rowincart, itemsCursor, from, to);

    setListAdapter(items);

    }


@Override
protected void onDestroy() {
    super.onDestroy();
    itemsCursor.close();
    readDatabase.close();
}

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
        ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);

    menu.setHeaderTitle("SMARTAWAY");

    menu.add(0, DELETE_ID, 1, "Delete Item");

    menu.add(0, UPDATE_ID, 1, "Change Quantity");
}

public boolean onContextItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case DELETE_ID:
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
                .getMenuInfo();
        readDatabase.deleteItem(info.id);
        fillData();
        return true;
    case UPDATE_ID:

        final AdapterContextMenuInfo info1 = (AdapterContextMenuInfo) item
                .getMenuInfo();
        final Dialog dialog = new Dialog(Cartactivity.this);
        dialog.setContentView(R.layout.dialog);
        final EditText edit0 = (EditText) dialog
                .findViewById(R.id.quantity);
        edit0.setText(String.valueOf(Quantity));
        Button ok = (Button) dialog.findViewById(R.id.ok);
        dialog.setTitle("          Add More Items          ");
        dialog.setCancelable(true);
        Button inc = (Button) dialog.findViewById(R.id.inc);
        inc.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                int c = Integer.parseInt(Quantity);
                c = c + 1;
                Quantity = String.valueOf(c);
                edit0.setText(Quantity);

            }
        });
        Button dec = (Button) dialog.findViewById(R.id.dec);
        dec.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                int c = Integer.parseInt(Quantity);
                c = c - 1;
                Quantity = String.valueOf(c);
                edit0.setText(Quantity);
            }
        });
        ok.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {

                row1 = info1.id; 
                flag = 1;
                int b = Integer.parseInt(Quantity);
                int total = cost * b;
                _total = String.valueOf(total);
                _cost = String.valueOf(cost);
                _quantity = String.valueOf(b);
                _item = product;

                Log.i(row1+" id"+_total +" total"+ _cost +" cost"+ _quantity+" quant", "Hello updated database");

                readDatabase.updateItem(row1, _item, _cost, _quantity, _total);

                fillData();

                dialog.dismiss();

            }
        });
        Button cancel = (Button) dialog.findViewById(R.id.cancel);
        cancel.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
            dialog.dismiss();   
            }
        });
        dialog.show();

        return true;
    }

    return super.onContextItemSelected(item);
}

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

    l.showContextMenuForChild(v);

    Cursor cursor = (Cursor) getListAdapter().getItem(position);
    Quantity = cursor.getString(cursor
            .getColumnIndex(DatabaseHandler.KEY_QUANTITY));
    /*Total = cursor.getString(cursor
            .getColumnIndex(DatabaseHandler.KEY_TOTAL));*/

}

All the things are going good here, but I found some errors in Logcat ie close() were not called explicitly on database something like this. The error doesnt stop my working anywhere but problem looks wierd. I think I have to close cursor but not sure about that. I have closed database on Destroy but not sure about cursor. Please help.

Same problem is mentioned here but didnt get the actual solution

Thanks in Advance

Upvotes: 2

Views: 2816

Answers (2)

Sahil Mahajan Mj
Sahil Mahajan Mj

Reputation: 11141

You should close your cursor object and the database object in the onDestroy() method,

if (itemsCursor!=null){
    itemsCursor.close();
}
if (readDatabase!=null){
    readDatabase.close();
}

Edit- Have you tried closing the cursor at the end of the fillData() function,

@SuppressWarnings("deprecation")
private void fillData() {
    readDatabase.open();
    itemsCursor = readDatabase.fetchAllItems();


    startManagingCursor(itemsCursor);

    String[] from = new String[] { DatabaseHandler.KEY_ITEM,
            DatabaseHandler.KEY_UNITCOST, DatabaseHandler.KEY_QUANTITY,
            DatabaseHandler.KEY_TOTAL };

    int[] to = new int[] { R.id.itemtext, R.id.costtext, R.id.quantitytext,
            R.id.totaltext };

    SimpleCursorAdapter items = new SimpleCursorAdapter(this,
            R.layout.rowincart, itemsCursor, from, to);

    setListAdapter(items);
    if (itemsCursor!=null){
    itemsCursor.close();
     }
    if (readDatabase!=null){
        readDatabase.close();
      }
    }

Upvotes: 1

Chinmoy Debnath
Chinmoy Debnath

Reputation: 2824

Colse your cursor every time after using then your problem will bo solved

itemsCursor.close()

As you are not closing this, resources of the cursor is not released for that reason when you close your db you are getting that error.

Make Your cursor as global variable then on your onDestroy

@Override
protected void onDestroy() {
    super.onDestroy();
    itemsCursor.close();
    db.close();
}

And as you are now adding close statement as a last statement of filldata method, the Adapter of listview doesn't get any data as cursor is already released for that reason you are not getting any data in listview.

Upvotes: 2

Related Questions