在elhadi的答案上展开我在跨多个异步任务打开和关闭数据库连接时遇到了类似的问题。从我当时的调查中可以清楚地看到,不必经常打开和关闭数据库连接。我最终采用的方法是对Application
进行子分类,并在onCreate
期间执行单个数据库打开和单个数据库关闭onTerminate
。然后我设置一个静态获取器来检索已经打开的SQLiteDatabase
对象。不是DI(依赖注入)友好,但Android还不能真正做到这一点。
类似这样;
public class MainApplication extends Application {
private static SQLiteDatabase database;
/**
* Called when the application is starting, before any other
* application objects have been created. Implementations
* should be as quick as possible...
*/
@Override
public void onCreate() {
super.onCreate();
try {
database = SQLiteDatabase.openDatabase("/data/data/<yourdbpath>", null, SQLiteDatabase.OPEN_READWRITE);
} catch (SQLiteException e) {
// Our app fires an event spawning the db creation task...
}
}
/**
* Called when the application is stopping. There are no more
* application objects running and the process will exit.
* <p>
* Note: never depend on this method being called; in many
* cases an unneeded application process will simply be killed
* by the kernel without executing any application code...
* <p>
*/
@Override
public void onTerminate() {
super.onTerminate();
if (database != null && database.isOpen()) {
database.close();
}
}
/**
* @return an open database.
*/
public static SQLiteDatabase getOpenDatabase() {
return database;
}
}
读的JavaDoc回来我肯定有从什么地方plagerised这一点,但你有这个静态单分贝开/关解决了这个问题。在另一个解释这个解决方案的地方有另一个答案。
更多细节:
针对Fr4nz的约低于NPE评论,我已经提供了具体实施的更多细节。
短版
下面的“全貌”难以把握,而不BroadcastReceivers有很好的理解。在你的情况下(并作为第一个)添加你的数据库创建代码并初始化并在创建数据库后打开数据库。所以写;
try {
database = SQLiteDatabase.openDatabase("/data/data/<yourdbpath>", null, SQLiteDatabase.OPEN_READWRITE);
} catch (SQLiteException e) {
// Create your database here!
database = SQLiteDatabase.openDatabase("/data/data/<your db path>", null, SQLiteDatabase.OPEN_READWRITE);
}
}
龙版
是的,不仅仅是上面的代码更给它一点点。请注意我对第一个例外情况的意见(即第一次运行应用程序)。这是说,“我们的应用程序触发产生数据库创建任务的事件”。实际上,我们的应用中发生的情况是,监听器(Android的BroadcastReceiver
框架)已注册,主要应用程序活动的第一件事情是检查MainApplication
中的database
静态变量是否为空。如果它是空的,那么会产生一个异步任务来创建数据库,当数据库完成时(即,运行onPostExecute()
方法)最终触发我们知道将被我们在try-catch中注册的侦听器拾取的事件。接收者作为内部类生活在MainApplication类下,看起来像这样;
/**
* Listener waiting for the application to finish
* creating the database.
* <p>
* Once this has been completed the database is ready for I/O.
* </p>
*
* @author David C Branton
*/
public class OpenDatabaseReceiver extends BroadcastReceiver {
public static final String BROADCAST_DATABASE_READY = "oceanlife.core.MainApplication$OpenDatabaseReceiver.BROADCAST_DATABASE_READY";
/**
* @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
*/
@Override
public void onReceive(final Context context, final Intent intent) {
Log.i(CreatedDatabaseReceiver.class.getSimpleName(), String.format("Received filter event, '%s'", intent.getAction()));
database = SQLiteDatabase.openDatabase("/data/data/<your db path>", null, SQLiteDatabase.OPEN_READWRITE);
unregisterReceiver(openDatabaseReceiver);
// Broadcast event indicating that the creation process has completed.
final Intent databaseReady = new Intent();
databaseReady.setAction(BROADCAST_DATABASE_READY);
context.sendBroadcast(databaseReady);
}
}
因此,第一次安装的启动过程总结如此;
- 类:MainApplication,角色检查是否有数据库?
- 是吗?数据库变量初始化
- 否?接收器注册(
OpenDatabaseReceiver
)
- 类:MainActivity:角色登陆活动的应用程序,并初步检查数据库变量是否为空。
database
为空?不添加执行I/O的片段,并添加对话框“创建应用程序数据库”或类似内容。
database
是不是空?继续执行主应用程序执行流程,添加由db等支持的列表。
- 类:DatabaseCreationDialogFragment:角色 - 产生异步任务来创建数据库。
- 注册监听数据库创建时的新接收器。
- 在收集“我创建数据库”消息时,会触发另一个事件(来自接收方)告诉应用程序打开数据库。
- 类:MainApplication:role 2-监听“数据库创建”消息。
- 上述接收器(
OpenDatabaseReceiver
)打开数据库并广播(通过另一事件!)数据库已准备好使用。
- 类:MainActivity:role 2-提取“数据库已准备就绪”消息,摆脱“我们正在创建数据库”对话框并继续显示应用程序中的数据/功能。
恢复和平。
不要忘记更新你的'''''''Manifest.xml'''',如果你尝试这个,请使用新的应用程序“名称”的路径。 – OceanLife
感谢您的回答 – Fr4nz
它解决了您的问题Fr4nz? – OceanLife