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

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




你可能感兴趣的:(Error处理:java.lang.IllegalStateException: databases already closed)