簡體   English   中英

Android SQLite數據庫在query()中關閉

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM