android - Usage CursorLoader without ContentProvider and avoiding database leaks
2021腾讯云限时秒杀,爆款1核2G云服务器298元/3年!(领取2860元代金券),
地址:https://cloud.tencent.com/act/cps/redirect?redirect=1062
2021阿里云最低价产品入口+领取代金券(老用户3折起),
入口地址:https://www.aliyun.com/minisite/goods
I have implemented the class found in this question:
Usage CursorLoader without ContentProvider
It is a means of using the LoaderManager and CursorLoader without a content resolver. I am using it to load data from a SQLite database and display it in a ListFragment.
The problem I am seeing is that the database is leaking. Obviously this is because I am not closing the database when I am done.
I have now started to do this, but I am concerned as the database could be accessed at any time by background tasks scheduled with the AlarmManager. I am worried that I might close the database when another class needs it open.
My solution has been to count the opens/closes and only close the database when no one is using it. Like so:
public synchronized SQLiteDatabase openDataBase()
{
try
{
mDatabaseUsers++;
Log.d(TAG, "DatabaseUsers: " + mDatabaseUsers);
// If already open, return it.
if (mOpenDatabase != null && mOpenDatabase.isOpen())
return mOpenDatabase;
OpenHelper openHelper = new OpenHelper(mContext);
return openHelper.getWritableDatabase();
} catch (SQLException e)
{
Log.e("MessageDelay", "Error opening database: " + e.toString());
return null;
}
}
public synchronized void closeDatabase()
{
mDatabaseUsers--;
// If no one is using the database, close it.
if (mOpenDatabase != null && mDatabaseUsers == 0)
{
mOpenDatabase.close();
}
Log.d(TAG, "DatabaseUsers: " + mDatabaseUsers);
}
This appears to work, but it has meant adding an extra line of code all over my application. Furthermore I've had trouble with the LoaderManager not behaving as expected and it calls its reset function more than it does its load, so I've had to put this fix in:
return new SimpleCursorLoader(getActivity())
{
private int mDBOpens = 0;
@Override
public Cursor loadInBackground()
{
mDBOpens++;
return JSQLite.getSingleton(getActivity()).retrieveTextsSent(mMode == 1 ? true : false);
}
@Override
public void reset()
{
if (mDBOpens > 0)
{
JSQLite.getSingleton(getContext()).closeDatabase();
}
super.reset();
mDBOpens--;
}
};
It feels like this isn't the correct way of doing it. Is there another, cleaner means of closing/opening the database only when needed?
Thanks, Jason.
android sqlite android-loadermanager android-cursorloader connection-leaks|
this question asked Dec 30 '12 at 14:15 Demonofloom 125 2 15 1 "Obviously this is because I am not closing the database when I am done." -- A
ContentProvider
does not close its database ever, either. –
CommonsWare Dec 30 '12 at 14:19 Thanks, that is interesting to know. –
Demonofloom Dec 30 '12 at 15:40
|
Know someone who can answer? Share a link to this question via email, Google+, Twitter, or Facebook.
相关阅读排行
- 1android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed
- 2Android SQLiteDatabaseLockedException: database is locked
- 3[连载 6/15] Android 从入门到精通Example 之 SQLite Database Example 2 - Extended Version
- 4处理Android SQLite - close() was never explicitly called on database异常
- 5android java.lang.IllegalStateException: database not open解决方法