当我尝试最初运行我的应用时,我试图重新打开已经关闭的对象。由于某种原因,它在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)*
答案 0 :(得分:0)
为什么在onCreate()
DatabaseHelper
方法之后调用db.close?
你不需要那个。
始终确保您没有连续两次调用open()
或close()
方法。您可以通过调用isOpen()
对象上的SQLDatabase
来检查您的数据库是否已打开。
请检查this link以了解有关此事的更多信息。