[英]Android SQLite database close in query()
我看到ContentProvider.query()返回一個Cursor對象。 通常,游標是SQLiteDatabase查詢的結果。 如以下代碼段所示:
public Cursor query() {
try {
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.query(Cfg.table_name, new String[] {"*"}, null, null, null, null, null);
return c;
}
catch(Exception exp) {
}
return null;
}
在代碼中,db未關閉。 有什么問題嗎?
是的,我相信有問題。 您可以將“ db”作為參數傳遞,然后在使用游標完成后,調用方可以將其關閉。
您是否要在完成后關閉數據庫? 如果是這樣,請嘗試:
public Cursor query() {
SQLiteDatabase db = null;
try {
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.query(Cfg.table_name, new String[] {"*"}, null, null, null, null, null);
return c;
}
catch(Exception exp) {
}finally{
try{if(null != db){ db.close(); db = null;}}catch(Exception e){}
}
return null;
}
那應該每次都正確關閉數據庫。 如果您想知道為什么它沒有關閉,我將調查Exception所說的內容。
順便說一句,我將用空值替換“ new String [] {” *“}”。 http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
更新:好的,現在我明白了這個問題。 但是,您可能需要稍微重組一下類。
TLDR:對我來說,理想的情況是,您應該參加兩節課。 一種是幫助您打開數據庫。 其次是將SQLiteDatabase對象保留為屬性。 創建此類(或創建用於打開數據庫的方法)后,您可以打開連接並初始化DB對象。 所有方法僅將db對象用於SCUD。 然后,所有關閉或分解的數據庫對象都可以放置在方法中或覆蓋onDestroy。 下面的示例,但是如果您有空的話,這是一個很好的教程http://www.vogella.de/articles/AndroidSQLite/article.html 。
第一個是DBOpenHelper。 此類的目的是管理表並幫助您打開數據庫進行修改。
package com.mondial.th.rsa.db;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
/**
* DBOpenHelper helps opening database and managing database's upgrade or creation.
* @author Poohdish Rattanavijai
*
*/
public class DBOpenHelper extends SQLiteOpenHelper {
private static final String TAG = DBOpenHelper.class.getSimpleName();
private static final int DATABASE_VERSION = 2;
private static final String DATABASE_NAME = "rsa_db";
public DBOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public DBOpenHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase database) {
Log.d(TAG, "DBOpenHelper.onCreate");
// Create table goes here.
}
@Override
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
// Drop and recreate table goes here.
}
}
第二個類將使用前面顯示的DBOpenHelper為您處理所有查詢。
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.mondial.th.rsa.vo.ProfileVO;
/**
* Database adapter for managing Profile table
* @author Poohdish Rattanavijai
*
*/
public class ProfileDBAdapter {
private static final String TAG = ProfileDBAdapter.class.getName();
private Context context;
private SQLiteDatabase db;
private DBOpenHelper dbHelper;
public ProfileDBAdapter(Context context){
this.context = context;
}
/**
* Open writable database.
* @return writable SQLDatabase
* @throws SQLException
*/
public ProfileDBAdapter open() throws SQLException{
Log.d(TAG, "Open ProfileDBAdapter");
dbHelper = new DBOpenHelper(context);
db = dbHelper.getWritableDatabase();
return this;
}
/**
* Close database; Exception omitted
*/
public void close(){
try {
dbHelper.close();
} catch (Exception e) {
//e.printStackTrace();
}
}
/**
* Creating new record in profile table with given VO.
* @param profile VO representing data in the new record.
* @return the row ID of the newly inserted row, or -1 if an error occurred.
*/
public long createProfile(ProfileVO profile){
ContentValues values = createContentValues(profile);
return db.insert(ProfileVO.TABLE_NAME, null, values);
}
/**
* Updating record in profile table with given VO by using ID column.
* @param profile VO representing new data to updated.
* @return the number of rows affected .
*/
public boolean updateProfile(ProfileVO profile){
ContentValues values = createContentValues(profile);
return db.update(ProfileVO.TABLE_NAME, values, ProfileVO.COLUMN_ID + "=" + profile.getId(), null) > 0;
}
/**
* Deleting a row representing given VO off profile table by using ID column.
* @param profile
* @return
*/
public boolean deleteProfile(ProfileVO profile){
return deleteProfile(profile.getId());
}
/**
* Deleting a row off profile table with given ID column.
* @param profile
* @return
*/
public boolean deleteProfile(long rowId){
return db.delete(ProfileVO.TABLE_NAME, ProfileVO.COLUMN_ID + "=" + rowId, null) > 0;
}
/**
* open cursor representing every records in profile table.
* @return Cursor representing every records in profile table.
*/
public Cursor fetchAllProfiles(){
return db.query(ProfileVO.TABLE_NAME, null, null, null, null, null, null);
}
/**
* open cursor representing a row in profile table with given ID.
* @return Cursor representing a row in profile table with given ID.
*/
public Cursor fetchProfile(long rowId){
Cursor mCursor = db.query(true, ProfileVO.TABLE_NAME, null, ProfileVO.COLUMN_ID + "=" + rowId
, null, null, null, null, null);
if(null != mCursor){
mCursor.moveToFirst();
}
return mCursor;
}
/**
* This class translate given VO into ContentValues for ContentResolver to parse data and talk to the database.
* @param profile VO
* @return ContentsValues containing given VO's data except ID.
*/
private ContentValues createContentValues(ProfileVO profile){
ContentValues values = new ContentValues();
values.put(ProfileVO.COLUMN_DOB, profile.getDob());
values.put(ProfileVO.COLUMN_FIRSTNAME, profile.getFirstname());
values.put(ProfileVO.COLUMN_LASTNAME, profile.getLastname());
return values;
}
}
然后,您將擁有一個充當DAO的完美班級。 對於上面的示例,用法是。
ProfileDBAdapter dbHelper = new ProfileDBAdapter(context);
dbHelper.open();
cursor = dbHelper.fetchAllProfiles();
if(cursor.getCount() > 0){
//TODO Data exists, do stuff.
}
try {
if(null != cursor && !cursor.isClosed()){
cursor.close();
}
} catch (Exception e) {
e.printStackTrace();
}
if(null != dbHelper){
dbHelper.close();
dbHelper = null;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.