源地址:http://www.androiddesignpatterns.com/2012/05/correctly-managing-your-sqlite-database.html
我注意到很多Android工程师都会遇到SQLiteDatabase相关的问题。我经常在StackOverflow遇到问这种错误信息的问题:
E/Database(234): Leak found
E/Database(234): Caused by: java.lang.IllegalStateException: SQLiteDatabase created and never closed
你或许知道这样的错误产生是因为没有关闭所有你打开的SQLiteDatabase实例。维护数据库对于刚开始学习Android的人来说有点复杂,特别对于那些还没把Activity生命周期搞清楚的人。最简单的方法是在你的整个应用生命周期中只创建一个单一数据库实例。这将保证不会出现泄露,因为这会降低你没关闭数据库的可能性,所以会让维护数据库更简单。
这里有两个例子,演示了维护单例数据库时三种情况, 保证在应用的生命周期中对数据库的安全访问。
情景1:使用单例来初始化SQLiteOpenHelper
将你的数据库帮助类声明为静态变量,并且使用单例模式来保证单例成员。下面的实例代码应该会帮助你正确设计数据库帮助类。
静态方法getInstance()保证在任何时刻都只存在一个数据库帮助类。如果sInstance对象没有被初始化,就会创建一个数据库帮助类实例。如果已经存在一个数据库帮助类实例,那么就简单地返回这个对象就好。你永远都
不要使用new DatabaseHelper(context)来初始化帮助类实例。而应该使用
DatabaseHelper.getInstance(context)来创建,能保证在整个应用生命周期内,只存在一个数据库帮助类实例。
public class DatabaseHelper extends SQLiteOpenHelper {
private static DatabaseHelper sInstance;
private static final String DATABASE_NAME = "database_name";
private static final String DATABASE_TABLE = "table_name";
private static final int DATABASE_VERSION = 1;
public static synchronized DatabaseHelper getInstance(Context context) {
// Use the application context, which will ensure that you
// don't accidentally leak an Activity's context.
// See this article for more information: http://bit.ly/6LRzfx
if (sInstance == null) {
sInstance = new DatabaseHelper(context.getApplicationContext());
}
return sInstance;
}
/**
* Constructor should be private to prevent direct instantiation.
* make call to static method "getInstance()" instead.
*/
private DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
}
情景2:把SQLiteDatabase封装在ContentProvider里面
这同样是一个比较好的技巧。据个例子,CursorLoader 类实例化需要ContentProvider类,如果你想让一个Activity或者Fragment和CursorLoader来实现接口LoaderManager.LoaderCallbacks<Cursor>(会在这篇博客里面进一步讨论:http://www.androiddesignpatterns.com/2012/07/understanding-loadermanager.html),需要为你的应用创建一个ContentProvider.而且,你不需要担心用ContentProvider如何维护数据库帮助类实例的单一性。只需要在Activity中调用getContentResolver(),系统就会帮你处理好一切(换句话说吗, 就是不用额外实现单例模式来防止多个实例被创建)。
如果你有任何问题,欢迎评论 或者 发给我邮件 zhangleicoding@163.com