Why does the cursor not close in android? - android

I have been trying every single thing but still some how have not been able to find a solution for this. In spite of using the close method the cursor still doesn't seem to be closing. This has been frustrating me. Any help will be much appreciated. Here is my code
public class Order extends Activity{
DatabaseHelper helper;
Cursor c;
SQLiteDatabase db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.order);
String columns[] = {"_id", "Name", "Price"};
helper = new DatabaseHelper(this);
db=helper.getWritableDatabase();
c=db.query("lite", columns, null, null, null, null, null);
c.moveToFirst();
curs();
c.close();
helper.close();
}
public void curs()
{
String r = "";
while(!c.isAfterLast())
{
r=r + c.getString(c.getColumnIndex("_id")) + " "+c.getString(c.getColumnIndex("Name"))+" "+c.getString(c.getColumnIndex("Price"));
c.moveToNext();
}
}

Modify
curs();
c.close();
helper.close();
to
curs();
if(!isClosed()){
c.close();
}
helper.close();
db.close();

You have not closed your database also, try this
db.close();
c.close();
helper.close();
Also, I suggest you can declare 'Cursor' as local variable instead of global and pass it as in argument to your method 'curs'

Related

Null Pointer Exception while fetching cursor object

I am getting null pointer exception while fetching the data from the SQLite table.
I am getting the null pointer exception when fetching the data using cursor like below Cursor c= db.fetchAllData();
Please have a look at the below precise code, and suggest me some ideas...
display_transaction.class
public class display_transaction extends Activity {
DisplayTestDBHelper db;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.display_listview);
displayListView();
}
public void displayListView() {
Cursor c= db.fetchAllData();
String[] columns={db.KEY_ID,db.KEY_DESCRIPTION,db.KEY_AMOUNT};
int[] id=new int[]{R.id.textView1,R.id.textView2};
SimpleCursorAdapter s=new SimpleCursorAdapter(this,R.layout.listviewlayout,c,columns,id,0);
ListView l=(ListView) findViewById(R.id.listview1);
l.setAdapter(s);
}
}
DisplayTestDBHelper.class
public Cursor fetchAllData() {
String TABLE_NAME="transaction_table";
SQLiteDatabase db = this.getWritableDatabase();
Cursor mCursor = db.query(TABLE_NAME, new String[] {KEY_ID, KEY_DESCRIPTION, KEY_AMOUNT}, null, null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
Please help me to resolve the above issue...
Thanks in advance!!!!
You didn't initialize db.
Depending on how you've implemented the helper's constructor, use something like
db = new DisplayTestDBHelper(this);
to init it, passing the activity this for a Context.
You haven't initialized db.
You need to do something like:
db = new DisplayTestDBHelper(this);

Cannot close the Db correctly

Following is my code,
public class CommentsDataSource {
private SQLiteDatabase database;
private MySQLiteHelper dbHelper;
private String[] allColumns = { MySQLiteHelper.COLUMN_ID,
MySQLiteHelper.COLUMN_COMMENT };
public CommentsDataSource(Context context) {
dbHelper = new MySQLiteHelper(context);
}
public void open() throws SQLException {
database = dbHelper.getWritableDatabase();
}
public void close() {
if (database != null) {
database.close();
}
dbHelper.close();
}
public String getComment_1() {
List<Comment> comments = new ArrayList<Comment>();
Cursor cursor = database.query(MySQLiteHelper.TABLE_COMMENTS,
allColumns, null, null, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
Comment comment = cursorToComment(cursor);
comments.add(comment);
cursor.moveToNext();
}
// make sure to close the cursor
cursor.close();
return comments.get(0).getComment();
}
private Comment cursorToComment(Cursor cursor) {
Comment comment = new Comment();
comment.setId(cursor.getLong(0));
comment.setComment(cursor.getString(1));
return comment;
}
public class MyService extends BackgroundService implements LocationListener {
#Override
public void onCreate() {
context = getApplicationContext();
datasource = new CommentsDataSource(context);
gps = new GPSTracker(context);
datasource.open();
mHelloTo = datasource.getComment_1();
datasource.close();
}
}
In the Above Code use to retrieve some data from database inside a Background Service. It Works Fine but Sometimes it gives the Following Error even though i close the cursor database and dbhelper correctly.
01-08 14:31:58.691: E/SQLiteDatabase(13854): close() was never explicitly called on database '/data/data/org.apache.cordova.example/databases/commments.db'
This only happens on platforms before JellyBean. JellyBean and later have this error message removed.
Even though it is logged with error log level and contains exception stacktrace, it is not an exception that was thrown. SQLiteDatabase constructor just stores the stacktrace of its caller in a member variable exception and in finalizer logs the stacktrace in case the database is still open.
You can see the stacktrace to see where the unclosed database was opened.
To get specific help with your code, include relevant parts of MySQLiteHelper in the question
Try changing this:
public String getComment_1() {
open(); // open database
List<Comment> comments = new ArrayList<Comment>();
Cursor cursor = database.query(MySQLiteHelper.TABLE_COMMENTS,
allColumns, null, null, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
Comment comment = cursorToComment(cursor);
comments.add(comment);
cursor.moveToNext();
}
// make sure to close the cursor
cursor.close();
close(); // close database
return comments.get(0).getComment();
}
Also what dbHelper.close(); does? You're closing the connection with the db calling database.close() so why do you need this?
You're calling the methods correctly, but please change the open() and close() methods to the following :
public void open() throws SQLException {
dbHelper= new MySQLiteHelper (ctx);
database = dbHelper.getWritableDatabase();
return this;
}
public void close() {
dbHelper.close();
}
But instead of opening and closing the database each time you make a read/write operation, I'd recommend you open() the database once in your Application.onCreate(). The closing will be done automatically when your application exits or is closed by Android OS. Since SQLite data integrity, you don't have to worry about losing data.

NullPointerException while opening database through a fragment

I am trying to populate the ListFragment from one of the columns in my Database.
For that i am trying to use
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
db.open();
db = new NotesDatabase(getActivity());
c = db.getAllRows();
getActivity().startManagingCursor(c);
String[] fromField = new String[] { NotesDatabase.KEY_TITLE };
int[] toView = new int[] { R.id.item_title };
SimpleCursorAdapter myCAdapter = new SimpleCursorAdapter(getActivity(),
R.layout.list_item, c, fromField, toView, 0);
setListAdapter(myCAdapter);
}
but i dont know why i am getting a NullPointerException on db.open(); and c = db.getAllRows();
db.open()
public NotesDatabase open() {
db = myDBHelper.getWritableDatabase();
return this;
}
db.getAllRows();
public Cursor getAllRows() {
String where = null;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS, where, null, null,
null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
DBHelper
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
or if there is a better a better way to populate the list view of fragment from a database?
Thanks in Advance :)
db.open();
db = new NotesDatabase(getActivity());
c = db.getAllRows();
Open the database
Create the database
Get all the rows.
Logically speaking. create it first. then open. then get all the rows. So swithc line 1 and lone 2.
Another thing is that , I assume your getting NPE at myDBHelper, because you never created that helper.
aren't you doing it reverse?
db.open();
db = new NotesDatabase(getActivity());
Just initialise your databasehelper before opening it:
db = new DatabaseHelper(this);
You are doing the db.open before the new so it doesn't exist yet, you are trying to open a null db.

Android IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase [duplicate]

This question already has an answer here:
attempt to re-open an already-closed object: SQLiteDatabase
(1 answer)
Closed 8 years ago.
I know there are several questions like this one, but all of them seem to have a different approach to solve the problem and none have solved mine.
I have my main activity working just fine, loading the db and populating the listview. Then I call a second activity and the problem shows up when I try to load the listview.
I have tried using start/stop managingcursor(cursor) even though it is deprecated, but it didn't fix the problem. Also I tried cloasing the cursor and db in my main activity before firing the next one but that didn't help either.
Both classes extend from ListActivity and follow the same sequence:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Open db in writing mode
MySQLiteHelper.init(this);
MySQLiteHelper tpdbh =
new MySQLiteHelper(this, "DB", null, 1);
SQLiteDatabase db = tpdbh.getWritableDatabase();
checkLocationAndDownloadData(); //this fires a Asynctask that calls method parseNearbyBranches shown bellow
//I load the data to the ListView in the postExecute method of the asynctask by calling:
/*
Cursor cursor = MysSQLiteHelper.getBranchesNames();
adapter = new SimpleCursorAdapter(this,
R.layout.row, cursor, fields, new int[] { R.id.item_text },0);
setListAdapter(adapter);
*/
ListView lv = getListView();
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View view,
int position, long id) {
// Get the cursor, positioned to the corresponding row in the result set
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
// Get the state's capital from this row in the database.
String branch_id = cursor.getString(cursor.getColumnIndexOrThrow("branch_id"));
cursor.close();
openNextActivity(Integer.parseInt(branch_id));
}
});
}
//In another file:
private void parseNearbyBranches(JSONObject jo) throws JSONException
{
if ( jo.has(jsonTitle) &&
jo.has("company_id") &&
jo.has("id")
) {
String branch = jo.getString(jsonTitle);
MySQLiteHelper tpdbh = MySQLiteHelper.instance;
SQLiteDatabase db = tpdbh.getWritableDatabase();
db.execSQL("INSERT INTO Branches (branch_id, name, company_id) " +
"VALUES ('" +jo.getInt("id")+"', '" + branch +"', '" +jo.getInt("company_id")+"' )");
db.close(); //no difference is I comment or uncomment this line
}
}
In MySQLiteHelper.java:
public static Cursor getBranchesNames() {
// TODO Auto-generated method stub
String[] columns = new String[] { "_id", "branch_id", "name", "company_id" };
Cursor c = getReadDb().query(branchesTable, columns, null, null, null, null,
null);
return c;
}
My other activity does basically the same:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_branch_surveys);
//Read branch data from DB
int companyID = -1;
MySQLiteHelper.init(this);
String [] columns = new String [] {"company_id"};
String [] args = {Integer.toString(branchID)};
Cursor c = MySQLiteHelper.getReadDb().query(MySQLiteHelper.branchesTable, columns, "branch_id=?", args, null, null, null); //THIS QUERY WORKS JUST FINE
if (c.moveToFirst())
companyID = Integer.parseInt(c.getString(0));
c.close();
if( companyID != -1)
{
new DownloadTask().execute(Integer.toString(companyID) );
//where the Async task calls something just like NearByBranches shown above(but with different objects of course)
//And the postExecute sets the listView:
/* cursor = MySQLiteHelper.getAll();
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.row, cursor, fields, new int[] { R.id.item_text },0);
setListAdapter(adapter);
*/
}
}
}
In MySQLiteHelper.java:
public static Cursor getAll() {
// TODO Auto-generated method stub
String[] columns = new String[] { "_id","title", "points" };
//********IT IS IN THIS LINE WHERE I GET THE ERROR:********************
Cursor c = getReadDb().query(theTable, columns, null, null, null, null,
null);
return c;
}
public static SQLiteDatabase getReadDb() {
if (null == db) {
db = instance.getReadableDatabase();
}
return db;
}
I hope you can help me out. Thanks!
I just tried commenting the db.close in the similar method of parseNeabyBranches and the problem was solved. Yet I dont get the same error having db.close() in parseNearbyBranches(), can you explain me why?
In parseNearbyBranches() you create a separate SQLiteDatabase object with:
SQLiteDatabase db = tpdbh.getWritableDatabase();
Since this is a different object than the one returned by getReadDb(), you can (and should) close it. The basic rule is each time you call getWritableDatabase() and getReadableDatable() you must have a matching close() statement.

android sqlite items

hi to all i have this android sqlite code to read all the titles from a table and this code is in the DBHelper.java
//---retrieves all the titles---
public Cursor getAllTitles()
{
return db.query(DATABASE_TABLE, new String[] {
KEY_ROWID,
KEY_BOOK,
KEY_AUTHOR,
KEY_EDITION,
KEY_YEAR,
KEY_RETURNDATE},
null,
null,
null,
null,
null);
and this is the code in my main app.....
//---get all titles---
db.open();
Cursor c = db.getAllTitles();
if (c.moveToFirst())
{
do {
DisplayTitle(c);
} while (c.moveToNext());
}
my question is that i want to get for example the returendate so i can compare it to the current time and based on that i will make an action
so can i read it ....buffer[5] and compare it....???
Assuming your return date is a string, you can use the following in your DisplayTitle(cursor c) :
String returnDate = c.getString(c.getColumnIndex(KEY_RETURNDATE));
public void doWork()
{
db.open();
Cursor c = db.getAllTitles();
if(c==null)
return;
for(c.moveToFirst();!c.isAfterLast();c.moveToNext())
{
String key= c.getString(c.getColumnIndex(c.getColumnName(5)));
//and now you can put the condition to compare current time with key
}
}
Use c.getString(c.getColumnIndex(KEY_RETURNDATE));as rajath said, and don't forget to close your Cursor after your loop if you don't need it any more: c.close(); else you will have a memory leak.

Categories

Resources