尝试重新打开已经关闭的对象

时间:2014-07-05 18:14:15

标签: android

当我尝试最初运行我的应用时,我试图重新打开已经关闭的对象。由于某种原因,它在buildCourseList方法中是一种轰炸,但直到方法调用结束时我才关闭数据库连接。知道我做错了什么吗?感谢

public class MainActivity extends ActionBarActivity {

//Create objects to match to UI views in the main activity
ImageButton addCourseButton;
ListView createdList;
DBAdapter myDBAdapter = new DBAdapter(this);

/** Will be used to create an ArrayList to hold the data in */
ArrayList<String> listToHoldValues= new ArrayList<String>();
ArrayList<String> assignmentList = new ArrayList<String>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);


    addCourseButton = (ImageButton)findViewById(R.id.btnAddCourse);
    createdList = (ListView)findViewById(R.id.listHolder);

    /*Create default list on create, which is the course list*/
    buildCourseList();
    setListViewItems();
}

/*************** Insertion Methods ************************************************************/
public void insertNewCourse(String newCourse){
    myDBAdapter.open();
    long id;
    id = myDBAdapter.insertCourse(newCourse);
    myDBAdapter.close();
}

public void insertNewCategory(String newCategory, String associatedCourse){
    myDBAdapter.open();
    long id;
    id= myDBAdapter.insertCategory(newCategory, associatedCourse);
    myDBAdapter.close();
}

public void insertNewGrade(
        int newGrade, String newAssignment, String associatedCourse, String associatedCategory){
    myDBAdapter.open();
    long id;
    id = myDBAdapter.insertGrade(newGrade, newAssignment, associatedCourse, associatedCategory);
    myDBAdapter.close();
}


/*************** Display Methods **************************************************************/
/* Will take the items from the Course table and insert them into an array*/
public void buildCourseList(){
    myDBAdapter.open();
    listToHoldValues.clear();       // Clear list to ensure that garbage isn't produced

    /*Provides access to the data in the database*/
    Cursor courseCursor = myDBAdapter.getAllCourses();

    /*Loops through the data in the course table to populate a list of courses to return to UI*/
    if(courseCursor.moveToFirst()){
        do{
            listToHoldValues.add(courseCursor.getString(1));
        }while (courseCursor.moveToNext());
    }
    myDBAdapter.close();
}

/* Will take the items from the Category table and insert them into an array*/
public void buildCategoryList(){
    myDBAdapter.open();
    listToHoldValues.clear();       // Clear list to ensure that garbage isn't produced

    /*Provides access to data in the database*/
    Cursor categoryCursor = myDBAdapter.getAllCategories();

    /*Loops through data in the category table to populate list of categories to return to ui*/
    if(categoryCursor.moveToFirst()){
        do {
            listToHoldValues.add(categoryCursor.getString(1));
        }while (categoryCursor.moveToNext());
    }
    myDBAdapter.close();
}

/* Will take the items from the Grade table and insert them into an array*/
public void buildGradeList(){
    myDBAdapter.open();
    listToHoldValues.clear();

    /*Provides access to the data in the database*/
    Cursor gradeCursor = myDBAdapter.getAllGrades();

    /*Loops through the data to populate list of assignments and grades to return to the UI*/
    if(gradeCursor.moveToFirst()){
        do {
            listToHoldValues.add(gradeCursor.getString(1));
            assignmentList.add(gradeCursor.getString(2));
        }while (gradeCursor.moveToNext());
    }
    myDBAdapter.close();
}

/**********************************Deletion Methods********************************************/

/*Will delete item from Course table depending course name passed in*/
public void deleteACourse(String course) {
    myDBAdapter.open();
    if (myDBAdapter.deleteCourse(course)) {
        Toast.makeText(this, course + " deleted!", Toast.LENGTH_LONG).show();
    } else {
        Toast.makeText(this, "Delete failed", Toast.LENGTH_LONG).show();
    }
    myDBAdapter.close();
}

/*Will delete item from Category table depending on the category name passed in*/
public void deleteACategory(String category){
    myDBAdapter.open();
    if(myDBAdapter.deleteCategory(category)){
        Toast.makeText(this, category + " deleted!", Toast.LENGTH_LONG).show();
    }else{
        Toast.makeText(this, "Delete failed!", Toast.LENGTH_LONG).show();
    }
    myDBAdapter.close();
}

/*Will delete item from grade table depending in assignment name passed in*/
public void deleteAGrade(String assignment){
    myDBAdapter.open();
    if (myDBAdapter.deleteCategory(assignment)){
        Toast.makeText(this, assignment + " deleted!", Toast.LENGTH_LONG).show();
    }else{
        Toast.makeText(this, "Delete failed!", Toast.LENGTH_LONG).show();
    }
    myDBAdapter.close();
}

/********************************** Update Methods ********************************************/
/*Will update requested course to new value*/
public void updateACourse(String courseToUpdate, String name){
    myDBAdapter.open();
    if(myDBAdapter.updateCourse(courseToUpdate, name)){
        Toast.makeText(this, "Update successful!", Toast.LENGTH_LONG).show();
    }else{
        Toast.makeText(this, "Update failed!", Toast.LENGTH_LONG).show();
    }
    myDBAdapter.close();
}

/*Will update requested category to new value*/
public void updateACategory(
        String categoryToUpdate, String courseCategoryIsIn, String updateName){
    myDBAdapter.open();
    if(myDBAdapter.updateCategory(categoryToUpdate, courseCategoryIsIn, updateName)){
        Toast.makeText(this, "Update successful!", Toast.LENGTH_LONG).show();
    }else{
        Toast.makeText(this, "Update failed!", Toast.LENGTH_LONG).show();
    }
    myDBAdapter.close();
}

/*Will updated a grade attached to an assignment to a new value*/
public void updateAGrade(String newGrade, String assignmentGradeAttachedTo,
                         String associatedCategory, String associatedCourse){
    myDBAdapter.open();
    if(myDBAdapter.updateGrade(newGrade, assignmentGradeAttachedTo,
            associatedCategory, associatedCourse)){
        Toast.makeText(this, "Update successful!", Toast.LENGTH_LONG).show();
    }else{
        Toast.makeText(this, "Update failed!", Toast.LENGTH_LONG).show();
    }
    myDBAdapter.close();
}


public double getCategoryAvg(){
    double average = 0.0;
    return average;
}

public double getCourseAverage(){
    double average = 0.0;
    return average;
}

/*Creates a ArrayAdapter to pass values to the list*/
public void setListViewItems(){
    ArrayAdapter<String> listAdapter = new ArrayAdapter<String>
            (this, android.R.layout.simple_list_item_1, listToHoldValues);

    // Set Adapter
    createdList.setAdapter(listAdapter);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

}

public class DBAdapter{
/*Constants needed for the database*/
static final String KEY_ROWID = "_id";              // id to reference class by
static final String KEY_COURSE = "course";          // name of course
static final String KEY_CATEGORY = "category";      // category of grade, homework, lab, etc
static final String KEY_GRADE = "grade";            // actual grade for an assignment
static final String KEY_ASSIGNMENT = "assignment";  // assignment grade is attached to
static final String TAG = "DBAdapter";

static final String DATABASE_NAME = "MyGrades";
static final String GRADE_TABLE = "gradeTable";
static final String CATEGORY_TABLE = "categoryTable";
static final String COURSE_TABLE = "courseTable";

static final int VERSION = 2;                       // upgrade with every change



static final String CREATE_TABLES = "CREATE TABLE gradeTable ("+
        "_id INTEGER PRIMARY KEY AUTOINCREMENT, grade INTEGER NOT NULL," +
        "assignment TEXT NOT NULL course TEXT NOT NULL, category TEXT NOT NULL);" +
        "CREATE TABLE categoryTable " +
        "(_id INTEGER PRIMARY KEY AUTOINCREMENT, category TEXT NOT NULL);" +
        "CREATE TABLE categoryTable " +
        "(_id INTEGER PRIMARY KEY AUTOINCREMENT, course TEXT NOT NULL);";

final Context context;

DatabaseHelper DBHelper;
SQLiteDatabase gradeDB;

// Constructor
public DBAdapter(Context ctx)
{
    this.context = ctx;
    DBHelper = new DatabaseHelper(context);
}

private static class DatabaseHelper extends SQLiteOpenHelper{
    DatabaseHelper(Context context){
        super(context, DATABASE_NAME, null, VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db){
        try{
            db.execSQL(CREATE_TABLES);
            /*db.execSQL(CREATE_GRADE_TABLE);
            db.execSQL(CREATE_COURSE_TABLE);
            db.execSQL(CREATE_CATEGORY_TABLE);*/
        }
        catch (SQLException e){
            e.printStackTrace();
        }
        db.close();
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
        Log.w(TAG, "Upgrading database form version " + oldVersion +
                " to " + newVersion + ", which will destroy all old data");
        db.execSQL("DROP TABLE IF EXISTS contacts");
        onCreate(db);
    }
}

// Open the database
public DBAdapter open() throws SQLException
{
    gradeDB = DBHelper.getWritableDatabase();
    return this;
}

// Close the database
public void close()
{
   DBHelper.close();
}

/**********************************************************************************************
 ****************** Insert Functions **********************************************************
 *********************************************************************************************/
// Insert new grade
public long insertGrade(
        int newGrade, String assignmentName, String gradeCourse, String gradeCategory)
{
    ContentValues insertingValues = new ContentValues();
    insertingValues.put(KEY_GRADE, newGrade);
    insertingValues.put(KEY_ASSIGNMENT, assignmentName);
    insertingValues.put(KEY_COURSE, gradeCourse);
    insertingValues.put(KEY_CATEGORY, gradeCategory);
    return gradeDB.insert(GRADE_TABLE, null, insertingValues);
}

// Insert new course
public long insertCourse(String courseName)
{
    ContentValues insertingValues = new ContentValues();
    insertingValues.put(KEY_COURSE, courseName);
    return gradeDB.insert(COURSE_TABLE, null, insertingValues);
}

// Insert new category
public long insertCategory(String categoryName, String courseName)
{
    ContentValues insertingValues = new ContentValues();
    insertingValues.put(KEY_CATEGORY, categoryName);
    insertingValues.put(KEY_COURSE, courseName);
    return gradeDB.insert(CATEGORY_TABLE, null, insertingValues);
}


/**********************************************************************************************
 ****************** SELECT Functions **********************************************************
 *********************************************************************************************/
// Retrieve all courses
public Cursor getAllCourses(){
    return gradeDB.query(COURSE_TABLE, new String[]{KEY_ROWID, KEY_COURSE},
            null, null, null, null, null);
}

// Retrieve all categories
public Cursor getAllCategories(){
    return gradeDB.query(CATEGORY_TABLE, new String[]{KEY_ROWID, KEY_CATEGORY},
            null, null, null, null, null);
}

// Retrieves all grades and their corresponding category and course
public Cursor getAllGrades(){
    return gradeDB.query(GRADE_TABLE,
            new String[]{KEY_ROWID, KEY_COURSE, KEY_CATEGORY, KEY_GRADE},
            null, null, null, null, null);
}


/**********************************************************************************************
 ****************** Delete Functions **********************************************************
 *********************************************************************************************/
// Delete a grade
public boolean deleteGrade(String assignment)
{
    return gradeDB.delete(GRADE_TABLE, KEY_ASSIGNMENT + "=" + assignment, null) > 0;
}

// Delete a course
public boolean deleteCourse(String courseName)
{
    return gradeDB.delete(COURSE_TABLE, KEY_COURSE + "=" + courseName, null) > 0;
}

// Delete a course
public boolean deleteCategory(String courseCategory)
{
    return gradeDB.delete(CATEGORY_TABLE, KEY_CATEGORY + "=" + courseCategory, null) > 0;
}


/**********************************************************************************************
 ****************** Update Functions **********************************************************
 *********************************************************************************************/
// updates a contact
public boolean updateCourse(String courseToUpdate, String name){
    ContentValues args = new ContentValues();
    String checkStatement = KEY_COURSE + "=" + courseToUpdate;
    args.put(KEY_COURSE, name);
    return gradeDB.update(COURSE_TABLE, args, checkStatement, null)>0;
}

// update a Category
public boolean updateCategory(
        String categoryToUpdate, String courseCategoryIsIn, String updateName){
    ContentValues args = new ContentValues();
    String checkStatement = KEY_CATEGORY + "=" + categoryToUpdate + " AND " +
            KEY_COURSE  + "=" + courseCategoryIsIn;
    args.put(KEY_CATEGORY, updateName);
    return gradeDB.update(CATEGORY_TABLE, args, checkStatement, null) > 0;
}

// Update a grade
public boolean updateGrade(String newGrade, String assignmentGradeAttachedTo,
                           String associatedCategory, String associatedCourse){
    ContentValues args = new ContentValues();
    String checkStatement = KEY_ASSIGNMENT + "=" + assignmentGradeAttachedTo + " AND " +
            KEY_CATEGORY + "=" + associatedCategory + " AND " +
            KEY_COURSE + "=" + associatedCourse;
    args.put(KEY_GRADE, newGrade);
    return gradeDB.update(GRADE_TABLE, args, checkStatement, null) > 0;
}

}

这就是logcat在轰炸时给我的东西:

*07-05 16:34:44.770    1027-1027/com.example.gradetracker.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.gradetracker.app, PID: 1027
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.gradetracker.app/com.example.gradetracker.app.MainActivity}: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/com.example.gradetracker.app/databases/MyGrades
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
            at android.app.ActivityThread.access$800(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/com.example.gradetracker.app/databases/MyGrades
            at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
            at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:520)
            at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:263)
            at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
            at com.example.gradetracker.app.DBAdapter.open(DBAdapter.java:100)
            at com.example.gradetracker.app.MainActivity.buildCourseList(MainActivity.java:68)
            at com.example.gradetracker.app.MainActivity.onCreate(MainActivity.java:37)
            at android.app.Activity.performCreate(Activity.java:5231)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
            at android.app.ActivityThread.access$800(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)*

1 个答案:

答案 0 :(得分:0)

为什么在onCreate() DatabaseHelper方法之后调用db.close? 你不需要那个。

始终确保您没有连续两次调用open()close()方法。您可以通过调用isOpen()对象上的SQLDatabase来检查您的数据库是否已打开。

请检查this link以了解有关此事的更多信息。