2012-02-03 9 views
0

ContentProvider.query()がCursorオブジェクトを返します。通常、カーソルはSQLiteDatabaseクエリの結果です。次のコードスニペットとして:Android SQLiteデータベースclose in query()

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は閉じられません。何か問題ある?

答えて

1

完了したらデータベースを閉じようとしていますか?そうしようとした場合 :

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 [] {" * "}"をnullに置き換えます。 http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html

更新:これで問題は分かりました。あなたは少しクラスを再構成する必要があるかもしれません。

TLDR:私にとって理想的なのは、2つのクラスになります。 1つは、DBのオープンを支援するためのものです。次にSQLiteDatabaseオブジェクトをプロパティとして保持します。このクラスを作成するとすぐに接続を開いてDBオブジェクトを初期化することができます(またはデータベースを開くためのメソッドの使用を作成する)。すべてのメソッドは、dbオブジェクトのみをSCUDに使用します。その後、すべてのdbオブジェクトのクローズまたは分解は、メソッドに置くことも、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として機能する完全なクラスが1つあります。上記の例では、使用方法は次のようになります。

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; 
} 
+0

ありがとうございますが、dbを閉じた後にカーソルが無効になる問題があります。 – Dagang

+0

私は答えを更新しました。それはちょっと長く、巻いていますが、それはあなたの問題を解決するのに役立ちます。 – RobGThai

+0

あなたの答えをありがとう!あなたのソリューションは、ユーザーがdbHelperオブジェクトを取得できるときに問題を解決します。しかし、私のケースでは、クエリーがコンテンツプロバイダー上にあるため、ユーザーはdbHelperオブジェクトを取得できません。だから、私はユーザーがデータベースを閉じることを期待することはできません。 – Dagang

2

はい、問題はあると思います。あなたは引数として 'db'を渡すことができ、呼び出し側はカーソルを使って終了することができます。

関連する問題