I am getting this exception in database Leak Found
my LOGCAT Shows this:
02-17 17:20:37.857: INFO/ActivityManager(58): Starting activity: Intent { cmp=com.example.brown/.Bru_Bears_Womens_View (has extras) }
02-17 17:20:38.477: DEBUG/dalvikvm(434): GC freed 1086 objects / 63888 bytes in 119ms
02-17 17:20:38.556: ERROR/Database(434): Leak found
02-17 17:20:38.556: ERROR/Database(434): java.lang.IllegalStateException: /data/data/com.example.brown/databases/BRUNEWS_DB_01.db SQLiteDatabase created and never closed
02-17 17:20:38.556: ERROR/Database(434): at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1694)
02-17 17:20:38.556: ERROR/Database(434): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:738)
02-17 17:20:38.556: ERROR/Database(434): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:760)
02-17 17:20:38.556: ERROR/Database(434): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:753)
02-17 17:20:38.556: ERROR/Database(434): at android.app.ApplicationContext.openOrCreateDatabase(ApplicationContext.java:473)
02-17 17:20:38.556: ERROR/Database(434): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:193)
02-17 17:20:38.556: ERROR/Database(434): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:98)
02-17 17:20:38.556: ERROR/Database(434): at com.example.brown.Brown_Splash.onCreate(Brown_Splash.java:52)
02-17 17:20:38.556: ERROR/Database(434): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
02-17 17:20:38.556: ERROR/Database(434): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
02-17 17:20:38.556: ERROR/Database(434): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
02-17 17:20:38.556: ERROR/Database(434): at android.app.ActivityThread.access$2200(ActivityThread.java:119)
02-17 17:20:38.556: ERROR/Database(434): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
02-17 17:20:38.556: ERROR/Database(434): at android.os.Handler.dispatchMessage(Handler.java:99)
02-17 17:20:38.556: ERROR/Database(434): at android.os.Looper.loop(Looper.java:123)
02-17 17:20:38.556: ERROR/Database(434): at android.app.ActivityThread.main(ActivityThread.java:4363)
02-17 17:20:38.556: ERROR/Database(434): at java.lang.reflect.Method.invokeNative(Native Method)
02-17 17:20:38.556: ERROR/Database(434): at java.lang.reflect.Method.invoke(Method.java:521)
02-17 17:20:38.556: ERROR/Database(434): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
02-17 17:20:38.556: ERROR/Database(434): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
02-17 17:20:38.556: ERROR/Database(434): at dalvik.system.NativeStart.main(Native Method)
how can i solve it???
thanks in advance...
You have to close your database
public DBAdapter open() throws SQLException
{
db = DBHelper.getWritableDatabase();
return this;
}
//---closes the database---
public void close()
{
DBHelper.close();
}
http://www.devx.com/wireless/Article/40842/1763?supportItem=4
You need to either close the database object or hold on to the database object so that there is a variable in your Content Provider that is referencing the database object allowing garbage collection to ignore the open database.
The problem with closing the database in the content provider is that the cursor being returned to the activity that requested the query becomes an empty cursor.
So the choice is to either hold on to the open database object for ever (the life time of the Content Provider) or to make sure that the database is closed when the cursor is closed.
I chose the second option and derived a cursor by extending the SQLiteCursor class and implementing the SQLiteDatabase.CursorFactory interface with the following code:
public class MyCursor extends SQLiteCursor
{
final SQLiteDatabase mDatabase;
final int mID;
public MyCursor(SQLiteDatabase database,
SQLiteCursorDriver driver,
String table,
SQLiteQuery query,
int cursorID)
{
super(database, driver, table, query);
mDatabase = database;
mID = cursorID;
}
/**
* Closes the database used to generate the cursor when the
* cursor is closed. Hopefully, plugging the GC Leak detected
* when using pure SQLiteCursor that are wrapped when returned
* to an Activity and therefore unreachable.
*/
@Override
public void close()
{
super.close();
if ( mDatabase != null )
{
mDatabase.close();
}
}
/**
* Closes cursor without closing database.
*/
public void closeForReuse()
{
super.close();
}
@Override
public String toString()
{
return super.toString() + ", ID# " + mID;
}
} // end of MyCursor class
//========================================================================
// Nested Class to create the MyCursor for queries
class MyCursorFactory implements SQLiteDatabase.CursorFactory
{
/**
* Creates and returns a new Cursor of MyCursor type.
*/
public Cursor newCursor ( SQLiteDatabase database,
SQLiteCursorDriver driver,
String editTable,
SQLiteQuery query )
{
int cursorID = MyProvider.CursorID++;
return new MyCursor(database,
driver,
editTable,
query,
cursorID);
}
} // end of MyCursorFactory class
This code provides a cursor object that closes the database when the cursor itself is closed, resolving the IllegalStateException during garbage collection. This does place the responsibility of closing the cursor on the activity that requested it. This should not put an extra burden on the activity since closing the cursor when done with it is good practice.
These two classes are nested inside of MyProvider, my content provider class and the data member CursorID is initialized by MyProvider.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With