Error处理:java.lang.IllegalStateException: databases already closed

本文分析了一个Android项目中出现的数据库操作错误:尝试关闭已关闭的数据库。问题出现在自定义的DBHelper类中,该类继承自SQLiteOpenHelper并实现了数据库的增删改查等操作。文章详细解释了为何直接调用SQLiteDatabase.close()而非SQLiteOpenHelper.close()会导致问题,并给出了正确的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android Error处理:java.lang.IllegalStateException: databases  already closed


今天导入一个基于Android 2.x版本SDK项目,运行的时候一直出错,错误如下:

11-18 16:58:56.595:E/AndroidRuntime(22991): java.lang.RuntimeException: Unable to start servicexxx.xxxx.service.LocalService@41985638 with Intent {act=xxx.xxx.xxx.APP_SERVICE (has extras) }: java.lang.IllegalStateException:database /data/data/xxx.xxx.xxx/databases/xxx.db (conn# 0) already closed


判断可能是数据库操作部分出了问题,数据库操作部分文件代码DBHelper.java如下:

package org.yousee.utils;


import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
/**
 * 存储记录的数据库
 */
public class DBHelper extends SQLiteOpenHelper {
	private Cursor c = null;
	private static final String CREATE_TAB = "create table "
		+ "music(_id integer primary key autoincrement,music_id integer,clicks integer," + "latest text)";
	private static final String TAB_NAME = "list";
	private SQLiteDatabase db = null;
	public DBHelper(Context context, String name, CursorFactory factory,int version) {
		super(context, name, factory, version);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		this.db = db;
		db.execSQL(CREATE_TAB);
	}
	
	public void insert(ContentValues values){
		SQLiteDatabase db = this.getWritableDatabase();
		db.insert(TAB_NAME, null, values);
		db.close();//应改为this.close()
	}

	public void update(ContentValues values,int id){
		SQLiteDatabase db = this.getWritableDatabase();
		db.update(TAB_NAME, values, "music_id="+id, null);
		db.close();//应改为this.close()

	}
	
	public void delete(int id){
		if (db == null){
			db = getWritableDatabase();
		}
		db.delete(TAB_NAME, "music_id=?", new String[]{String.valueOf(id)});
	}
	
	public Cursor query(int id){
		SQLiteDatabase db = getReadableDatabase();
		c = db.query(TAB_NAME, null, "music_id=?", new String[]{String.valueOf(id)}, null, null, null);
		db.close();//应改为this.close()

		return c;
	}
	
	public Cursor queryByClicks(){//按点击量查询
		SQLiteDatabase db = getReadableDatabase();
		c = db.query(TAB_NAME, null, null, null, null, null, "clicks desc");
		return c;
	}
	
	public Cursor queryRecently(){//按时间降序查询
		SQLiteDatabase db = getReadableDatabase();
		c = db.query(TAB_NAME, null, null, null, null, null, "latest desc");
		return c;
	}
	
	public void close(){
		if (db != null){
			db.close();//应改为this.close()

			db=null;
		}
		if (c!=null){
			c.close();
			c=null;
		}
	}
	
	@Override
	public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {

	}

}
经过 分析发现是关闭数据库时直接调用了SQLiteDatabase.close()方法。


出错的具体原因为:

如果调用SQLiteDatabase.close()代替SQLiteOpenHelper.close()。那么SQLiteOpenHelper就不知道通过helper获取的DB是否是关闭的(getReadableDatabase或getWritableDatabase)。

总结:

1、SQLiteOpenHelper.close()是异步的,而SQLiteDatabase.close()不是。

2、在使用安卓提供的SQLiteOpenHelper时,通过getReadableDatabase或getWritableDatabase获得的其实是同一个对象,唯一的却别就是如果你的硬盘不足了,那么你就不能在调用getWritableDatabase,只能调用getReadableDatabase。

3、使用Android提供的数据库接口进行数据库操作的时候一定要遵循Andoid的规则。在多线程中要注意,所以养成好的面向对象的习惯,调用helper的close方法关闭数据库。(谁提供的数据,就调用谁的方法来操作数据)



网上还看到有类似的问题:

http://androiddev.orkitra.com/?p=30756

http://stackoverflow.com/questions/6535908/android-sqlite-sqliteopenhelper-error-illegalstateexception-db-already-clo




Caused by: java.lang.IllegalStateException: Logback configuration error detected的问题是由于Logback配置错误引起的。根据引用和引用的信息,可能的解决办法如下: 1. 检查Logback的配置文件,确保配置文件的语法和结构正确。可以尝试重新编写或更新Logback配置文件。 2. 检查Logback依赖是否正确添加到项目的依赖管理中。可以使用Maven或Gradle等构建工具来管理项目的依赖。 3. 检查Logback的日志输出路径和文件权限,确保日志文件可以被正常写入。 4. 检查Logback的日志输出级别,确保日志级别的设置与期望的输出一致。 5. 检查Logback的相关组件和库是否与项目的其他组件和库版本兼容,避免引起冲突或不兼容问题。 6. 如果以上方法都无法解决问题,可以尝试搜索相关错误信息和解决方案,参考引用提供的Android Caused by: java.lang.ClassNotFoundException解决办法的相关资料,看是否能找到类似的解决方法来解决Logback配置错误的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [关于Caused by: java.lang.IllegalStateException:问题解决办法!](https://blog.csdn.net/m0_52255061/article/details/115248503)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [Android Caused by: java.lang.ClassNotFoundException解决办法](https://download.csdn.net/download/weixin_38703295/12784351)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JerryHe

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值