我的Android应用程序出了问题。我正在使用代码bellow在AsyncTask中打开SQLite数据库。一切正常,但当我尝试使用onStop()
或onDestroy
方法关闭数据库时,它永远不会关闭。
创建和打开数据库的代码:
公共类SQLiteDB扩展了SQLiteOpenHelper {
private final Context context;
private SQLiteDatabase sqliteDatabase = null;
public SQLiteDB(Context context, String DBName) {
super(context, DBConstant.DB_NAME, null, context.getResources().getInteger(ppredota.android.navigation.view.activities.R.string.database_version));
this.context = context;
}
public void createDB() throws IOException{
if(existDB()){
this.getReadableDatabase();
this.close();
}
else {
this.getWritableDatabase();
try {
copyDB();
this.close();
}
catch (Exception e) {
throw new Error("Chyba pri kopirovani databaze");
}
}
}
private boolean existDB() {
SQLiteDatabase checkDatabase = null;
try{
String fullPath = DBConstant.DB_PATH + DBConstant.DB_NAME;
checkDatabase = SQLiteDatabase.openDatabase(fullPath, null, SQLiteDatabase.OPEN_READWRITE);
}
catch (SQLiteException sqle) {
Log.i("existDB()", "Databaze nelze otevrit, neexistuje");
}
if(checkDatabase == null){
Log.i("existDB", "Databaze jeste neexistuje...");
return false;
}
else{
Log.i("existDB", "Databaze uz existuje...");
checkDatabase.close();
return true;
}
}
private void copyDB() throws IOException {
InputStream inDBStream = context.getAssets().open(DBConstant.DB_NAME);
String newDBPath = DBConstant.DB_PATH + DBConstant.DB_NAME;
OutputStream outDBStream = new FileOutputStream(newDBPath);
Log.i("copyDB", "Otevren outputstream s cestou k nove databazi");
byte[] buffer = new byte[1024];
int length;
while ((length = inDBStream.read(buffer))>0){
outDBStream.write(buffer, 0, length);
}
outDBStream.flush();
outDBStream.close();
inDBStream.close();
}
public void openDB() throws SQLException {
String fullPath = DBConstant.DB_PATH + DBConstant.DB_NAME;
if(sqliteDatabase!=null){
if(sqliteDatabase.isOpen()){
Log.i("openDB()", "Databaze je jiz otevrena");
}
else{
sqliteDatabase = SQLiteDatabase.openDatabase(fullPath, null, SQLiteDatabase.OPEN_READONLY);
Log.i("openDB()", "Databaze" + sqliteDatabase.getPath() + "otevrena");
}
}
else{
sqliteDatabase = SQLiteDatabase.openDatabase(fullPath, null, SQLiteDatabase.OPEN_READONLY);
if(sqliteDatabase.isOpen()){
Log.i("openDB()", "Databaze otevrena");
}
}
}
@Override
public void close() {
if(sqliteDatabase!=null){
sqliteDatabase.close();
Log.i("close()", "Databaze zavrena");
}
super.close();
}
public SQLiteDatabase getSQLiteDatabase() {
if(sqliteDatabase==null){
Log.i("getSQLiteDatabase()","Problem, vraci sqliteDatabase = null");
}
else{
Log.i("getSQLiteDatabase()","instance sqliteDatabase vracena bez problemu");
}
return sqliteDatabase;
}
AssyncTask类:
公共类OpenDatabaseTask扩展了AsyncTask {
private Context context;
private SQLiteDB sqliteDB;
public OpenDatabaseTask(Context context,SQLiteDB sqliteDB) {
this.context = context;
this.sqliteDB = sqliteDB;
}
@Override
protected Void doInBackground(Void... params) {
publishProgress();
try {
sqliteDB.createDB();
} catch (IOException e) {
e.printStackTrace();
}
sqliteDB.openDB();
return null;
}
@Override
protected void onProgressUpdate(Void...unused){
Log.i(OpenDatabaseTask.class.toString(), "Spusteno vlakno");
}
}
和活动(仅限重要部分):
private SQLiteDB sqliteDB;
private SQLiteData sqliteData;
private OpenDatabaseTask openDatabaseTask;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.navigatemenu);
sqliteDB = new SQLiteDB(getApplicationContext(), sourceDatabaseName);
openDatabaseTask = new OpenDatabaseTask(getApplicationContext(), sqliteDB);
openDatabaseTask.execute();
protected void onDestroy(){
super.onDestroy();
Log.i("onDestroy()", "Pokus o zavreni databaze");
//here is the problem, database never closed
sqliteDB.close();
}
protected void onStop(){
super.onStop();
Log.i("onStop()", "Pokus o zavreni databaze");
//here is the problem, database never closed
sqliteDB.close();
}
protected void onPause(){
super.onPause();
}
protected void onResume(){
super.onResume();
//Log.i("onResume()", "Pokus o otevreni databaze");
}
}
因此,当我尝试使用close()
方法关闭数据库时,sqliteDatabase始终为null,并且数据库永远不会关闭。因此,数据库仍然打开,并在调用onDestroy
异常后发生。
感谢您的时间,对不起我的英语,我是捷克语:)
答案 0 :(得分:0)
只是一个猜测(假设您想要关闭销毁)
在调用super
之前关闭数据库protected void onDestroy(){
// close befor super is called
sqliteDB.close();
super.onDestroy();
Log.i("onDestroy()", "Pokus o zavreni databaze");
// sqliteDB.close(); // super.onDestroy may already has destroyed the DB
}
注意:
假设数据库仅存在且在活动可见时打开,您应该在onResume()中打开数据库并在onPause()中关闭它。
如果数据库应该在代码加载到内存时打开,请在onCreate中创建并在onDestroy中关闭它
在您的示例中,您在onCreate中打开它并在onStop中将其关闭。 问题:当活动第二次看到数据库关闭时可见。 有关详细信息,请参阅android activity documentation并查看按钮上的应用程序生命周期。
答案 1 :(得分:0)
我有一个重度数据库交互的应用程序。我没有用户帮助。我的数据库在UI线程和后台线程中打开很多次,但从未关闭过。到目前为止没有任何问题,不知道这是否是正确的做法...