没有在数据库上显式调用close()

时间:2011-02-07 12:56:00

标签: java android sqlite

我需要知道在我的代码中调用db.close()的位置。我已经在onCreate()方法中添加了它,但是当我需要使用某些方法时,它表示数据库没有打开,然后我从onCreate()中删除它并且它表示close()没有被明确调用。那么我应该在哪里关闭,它可以在类的每个方法中吗?

这是代码:

public class HoursPerDayDataHelper {

private static final String DATABASE_NAME = "database.db";
private static final int DATABASE_VERSION = 1;
protected static final String TABLE_NAME = "table";
protected String TAG = "HoursPerDayDataHelper";

private Context context;
private SQLiteDatabase db;
OpenHelper openHelper = null;

public HoursPerDayDataHelper(Context context) {
    this.context = context;
    openHelper = new OpenHelper(this.context);
    this.db = openHelper.getWritableDatabase();
    openHelper.onCreate(db);

}

public void close() {

    if (openHelper != null) {
        openHelper.close();
    }

}

public void deleteAll() {
    this.db.delete(TABLE_NAME, null, null);
}

public String selectDuration(String date) {

    String duration = "";
    Integer value = 0;
    String returnment = "";
    Log.i(TAG, "date do select: " + date);              

    Cursor cursor = this.db.query(TABLE_NAME, new String[] { "duration" },
            "date = ? ", new String[]{ date }, null, null, null);

    Log.i(TAG, "cursor string " + cursor);

    if (cursor.moveToFirst()) {
        do {
            Log.i(TAG, "dentro do if cursor");
            duration = cursor.getString(0);
            value += Integer.parseInt(duration);

        } while (cursor.moveToNext());
        returnment = Integer.toString(value);
    }else{

        Log.i(TAG, "bla bla bla");

    }

    if (cursor != null && !cursor.isClosed()) {
        cursor.close();

    }
    return returnment;
}

public ArrayList<String[]> selectTopContacts() {

    ArrayList<String[]> list1 = new ArrayList<String[]>();
    Cursor cursor = this.db.query(TABLE_NAME, null, null, null, null, null,
            "duration desc");

    if (cursor.moveToFirst()) {
        do {
            if (cursor.getString(2) != "") {

                String[] data = new String[4];
                data[0] = cursor.getString(2);
                data[1] = cursor.getString(4);
                data[2] = cursor.getString(5);
                data[3] = cursor.getString(7);

                list1.add(data);

            } else {

                String[] data = new String[3];
                data[1] = cursor.getString(4);
                data[2] = cursor.getString(5);
                data[3] = cursor.getString(7);

                list1.add(data);

            }
        } while (cursor.moveToNext());
    }
    if (cursor != null && !cursor.isClosed()) {
        cursor.close();

    }
    return list1;
}

public static class OpenHelper extends SQLiteOpenHelper {

    OpenHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE IF NOT EXISTS "
                + TABLE_NAME
                + "(id INTEGER PRIMARY KEY AUTOINCREMENT, duration TIME, date DATE, current_time TIME)");

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.w("HoursPerDay Database",
                "Upgrading database, this will drop tables and recreate.");
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(db);
    }
}

}

这是我的活动:

public class HoursPerDay extends Activity{

private String LOG_TAG = "HoursPerDay";
private TextView mDateDisplay;
public String date;
private int mYear;
private int mMonth;
private int mDay;
private int newDay;
private String hpdData; 
private HoursPerDayDataHelper hpd;

OpenHelper openHelper = new OpenHelper(HoursPerDay.this);

static final int DATE_DIALOG_ID = 0;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.hours_per_day);

    hpd = new HoursPerDayDataHelper(this);

    // capture our View elements
    mDateDisplay = (TextView) findViewById(R.id.dateDisplay);   

    // get the current date
    final Calendar c = Calendar.getInstance();
    mYear = c.get(Calendar.YEAR);
    mMonth = c.get(Calendar.MONTH);
    mDay = c.get(Calendar.DAY_OF_MONTH);
    // display the current date (this method is below)
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (openHelper != null) {
        openHelper.close();
    }
    if (hpd != null) {
        hpd.close();
    }
}

// the callback received when the user "sets" the date in the dialog
private DatePickerDialog.OnDateSetListener mDateSetListener = new DatePickerDialog.OnDateSetListener() {

    public void onDateSet(DatePicker view, int year, int monthOfYear,
            int dayOfMonth) {

        mYear = year;
        mMonth = monthOfYear;
        mDay = dayOfMonth;                  

        setBasicContent();

        hpd.close();


    }
};

protected Dialog onCreateDialog(int id) {
    switch (id) {
    case DATE_DIALOG_ID:
        return new DatePickerDialog(this,
                    mDateSetListener,
                    mYear, mMonth, mDay);
    }
    return null;
}

@Override
public boolean onCreateOptionsMenu(Menu menu){

    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.layout.hoursperdaymenu, menu);
    return true;

}

@Override
public boolean onOptionsItemSelected(MenuItem item){

    switch(item.getItemId()){

    case R.id.filter_by_day:            
            showDialog(DATE_DIALOG_ID);
            return true;
    case R.id.filter_by_user:

        showDialog(DATE_DIALOG_ID);
        return true;

    default:
        return super.onOptionsItemSelected(item);
    }

}   

public void setBasicContent() {

    date = (mMonth + 1) + "/" + newDay + "/" + mYear;       
    hpdData = this.hpd.selectDuration(date);
    mDateDisplay.setText(hpdData);
    hpd.close();
}

}

2 个答案:

答案 0 :(得分:2)

我认为有两种方法:

  • onPause - 方法并检查isFinishing是否 - &gt;关。问题:如果你的应用程序被app-killer杀死,db仍然保持打开状态。
  • 每次(读取/写入)时打开和关闭数据库。

修改
好的,我明白为什么会造成这种情况。我想你误解了SQLiteOpenHelper的用法。你永远不必打电话给onCreate - 方法 有缺陷的更好的方法是制作DBHelper课程并在单独的通话中使用它,让我们说SQLDataHandler
你的活动看起来不错。我改变了一些东西,看看它是否有帮助。我会给他们留下标记:

这就是Helper类中的所有内容:

public static class OpenHelper extends SQLiteOpenHelper {

 private static final String DATABASE_NAME = "database.db";
 private static final int DATABASE_VERSION = 1;
 protected static final String TABLE_NAME = "table";
 protected String TAG = "HoursPerDayDataHelper";

保留CREATE TABLE只有在没有现有的情况下才会创建/调用它。
如果String直接传递

,我发现错误
 @Override
 public void onCreate(SQLiteDatabase db) {

    String query = "CREATE TABLE "
               + TABLE_NAME
               + "(id INTEGER PRIMARY KEY AUTOINCREMENT, duration TIME, date DATE,          current_time TIME)";
    db.execSQL(query);
    }
 }

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}

 OpenHelper(Context context) {
     super(context, DATABASE_NAME, null, DATABASE_VERSION);
 }
}

使用它:
只需拨打DataHandler课程:

OpenHelper helper = new OpenHelper(ctx);
// SQLiteDatabase db = helper.getReadableDatabase();
SQLiteDatabase db = helper.getWritableDatabase();

所有其他内容,如删除,添加等,都应在“DataHandler”类中完成 只需使用相同的两种方法来获取数据库。最后,当您完成后,您就可以在DataHandlerdb.close()打电话 像这样,活动本身从不直接使用de DB。我认为更好的做法;)

我希望它有所帮助。对于任何其他问题,请问:)


EDIT2:

首先,一般来说它应该与内部类一起工作 但是:如果你想从另一个类添加另一个表,它将不再起作用。这就是为什么从一开始就将它放在一个单独的类中的更好方法。它甚至可以重复使用(进行一些小调整) 把我发布的代码放在OpenHelper类中。没什么。
然后,将数据操作内容放在一个名为“ DataHandlerDB ”的类中。

代码示例:

package ...;

import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class DataHandlerDB {

  public static void persistAll(Context ctx, List<Module> moduleList) {

      DatabaseHelper helper = new DatabaseHelper(ctx);

      SQLiteDatabase db = helper.getWritableDatabase();

      ContentValues values = new ContentValues();
      for (Module m : moduleList) {

          values.put("_id", m.get_id());
          values.put("name", m.getModule());

          db.insert("module", null, values);
      }
      db.close();
  }

  public static List<Module> findAll(Context ctx) {

      List<Module> result = new ArrayList<Module>();
      DatabaseHelper helper = new DatabaseHelper(ctx);
      SQLiteDatabase db = helper.getReadableDatabase();

      Cursor c = db.query(ModuleDB.TABLE_NAME, new String[] { ModuleDB.ID,
            ModuleDB.MODULE}, null, null, null, null, null);

      while (c.moveToNext()) {
          Module m = new Module(c.getInt(0), c.getString(1));
          result.add(m);
      }
      c.close();
      db.close();

      return result;
  }

  // Update Database entry
  public static void update(Context ctx, Module m) {

      DatabaseHelper helper = new DatabaseHelper(ctx);
      SQLiteDatabase db = helper.getWritableDatabase();
      ContentValues values = new ContentValues();

      values.put("_id", m.get_id());
      values.put("name", m.getModule());

      db.update("module", values, null, null);
      db.close();
  }

  public static void delete(Context ctx, Module m) {

      DatabaseHelper helper = new DatabaseHelper(ctx);
      SQLiteDatabase db = helper.getWritableDatabase();
      ContentValues values = new ContentValues();

      values.put("_id", m.get_id());
      values.put("name", m.getModule());

      db.delete("module","_id = m.get_id()", null);
      db.close();
  }

  public static void createDB(Context ctx) {
      DatabaseHelper helper = new DatabaseHelper(ctx);
      SQLiteDatabase db = helper.getWritableDatabase();
      db.close();
  }
}

为了提高方法static的效率,您不需要创建对象 像这样使用:在您的活动中

    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

            // get the a writable DB, in case it's not existing it gets created.
    DataHandlerDB.createDB(this);
    // get stuff out of DB
    moduleList = DataHandlerDB.findAll(this);

    adapter = new ArrayAdapter<Module>(this,
            android.R.layout.simple_list_item_1, moduleList);
    setListAdapter(adapter);
}

答案 1 :(得分:0)

如果在onCreate中打开,则关闭onDestroy