Close() никогда явно не вызывалась в базе данных даже после реализации close()

Eclipse показывает мне вышеуказанную ошибку, хотя я реализовал указанный метод close().

Вот код:

public void update_project(View view) {

    EditText cinone = (EditText) findViewById(R.id.pname);
    pname = cinone.getText().toString();

    String fDate = pday + ". " + pmonth + ". " + pyear;

    projectdatabase dbupdate = new projectdatabase(UpdateProject.this);

    dbupdate.open();
    dbupdate.updateProject(id, pname, fDate); 
    dbupdate.close();

}

Логкат:

12-31 22:05:51.114: E/SQLiteDatabase(4180): close() was never explicitly called on  
database '/data/data/com.kk.project/databases/project_db' 
12-31 22:05:51.114: E/SQLiteDatabase(4180):  
android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the     
cursor or database object that was opened here
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at  
android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1943)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at 
android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1007)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at   
android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:986)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at 
android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1051)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at 
android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:770)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at  
android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at 
android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:157)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at     
com.kk.project.projectdatabase.open(projectdatabase.java:66)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at  
com.kk.project.ProjectExplorer.getinfo(ProjectExplorer.java:30)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at    
com.kk.project.ProjectExplorer.onCreate(ProjectExplorer.java:25)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at  
android.app.Activity.performCreate(Activity.java:4465)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at  
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at 
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at 
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at  
android.app.ActivityThread.access$600(ActivityThread.java:123)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at 
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at  
android.os.Handler.dispatchMessage(Handler.java:99)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at 
android.os.Looper.loop(Looper.java:137)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at  
android.app.ActivityThread.main(ActivityThread.java:4424)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at   
java.lang.reflect.Method.invokeNative(Native Method)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at     
java.lang.reflect.Method.invoke(Method.java:511)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at 
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at   
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
12-31 22:05:51.114: E/SQLiteDatabase(4180):     at 
dalvik.system.NativeStart.main(Native Method)
12-31 22:05:51.165: E/System(4180): Uncaught exception thrown by finalizer
12-31 22:05:51.174: D/dalvikvm(4180): GREF has increased to 201
12-31 22:05:51.204: I/dalvikvm(4180): threadid=3: reacting to signal 3
12-31 22:05:51.324: E/System(4180): java.lang.IllegalStateException: Don't have   
database lock!
12-31 22:05:51.324: E/System(4180):     at  
android.database.sqlite.SQLiteDatabase.verifyLockOwner(SQLiteDatabase.java:2090)
12-31 22:05:51.324: E/System(4180):     at  
android.database.sqlite.SQLiteDatabase$1.entryRemoved(SQLiteDatabase.java:2182)
12-31 22:05:51.324: E/System(4180):     at   
android.database.sqlite.SQLiteDatabase$1.entryRemoved(SQLiteDatabase.java:2178)
12-31 22:05:51.324: E/System(4180):     at  
android.util.LruCache.trimToSize(LruCache.java:197)
12-31 22:05:51.324: E/System(4180):     at   
android.util.LruCache.evictAll(LruCache.java:285)
12-31 22:05:51.324: E/System(4180):     at   
android.database.sqlite.SQLiteDatabase.deallocCachedSqlStatements  
(SQLiteDatabase.java:2143)
12-31 22:05:51.324: E/System(4180):     at  
android.database.sqlite.SQLiteDatabase.closeClosable(SQLiteDatabase.java:1126)
12-31 22:05:51.324: E/System(4180):     at  
android.database.sqlite.SQLiteDatabase.finalize(SQLiteDatabase.java:1914)
12-31 22:05:51.324: E/System(4180):     at   
java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:182)
12-31 22:05:51.324: E/System(4180):     at  
java.lang.Daemons$FinalizerDaemon.run(Daemons.java:168)
12-31 22:05:51.324: E/System(4180):     at java.lang.Thread.run(Thread.java:856)

Странно то, что я очень ценил подобный код, и он работал безупречно. Кроме того, другие методы из того же класса базы данных работают отлично.

Код действия, вызывающего updateProject:

public class UpdateProject extends Activity implements OnItemSelectedListener,  DatePickerDialog.OnDateSetListener {

int mPos;
String mSelection;

String pname;
String pdifficulty;

int pday;
int pmonth;
int pyear;

String id;


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

    id = getIntent().getExtras().getString("idforupdate");

    userdatabase viewname = new userdatabase(this);             //Get username
    viewname.open();
    String name = viewname.getusername();
    viewname.close();

    if(name.equals("")) {

        DialogFragment newFragment = new NouserexitFragment();
        newFragment.show(getFragmentManager(), "exit");

    }

    Spinner spinner = (Spinner) findViewById(R.id.difficultyspinner); ArrayAdapter<CharSequence> 
    adapter = ArrayAdapter.createFromResource(this,R.array.difficultyarray, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);
    spinner.setOnItemSelectedListener(this);

    pdifficulty = spinner.getSelectedItem().toString();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_update_project, menu);
    return true;
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void datepicker(View v) {                                                        //Date picker   
    DialogFragment newFragment = new DatePickerForUpdate();
    newFragment.show(getFragmentManager(), "datePickerforupdate");

}


    @Override
public void onDateSet(DatePicker view, int year, int month, int day) {
    // TODO Auto-generated method stub

    pday = day;
    pmonth = month +1;
    pyear = year;

    month = month + 1;
    Button activityButton = (Button)findViewById(R.id.datebutton);
    activityButton.setText (day + "." + month + "." + year);

}

@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
    // TODO Auto-generated method stub

    UpdateProject.this.mPos = pos;
    UpdateProject.this.mSelection = parent.getItemAtPosition(pos).toString();

}

@Override
public void onNothingSelected(AdapterView<?> arg0) {
    // TODO Auto-generated method stub

}

public void update_project(View view) {

EditText cinone = (EditText) findViewById(R.id.pname);
pname = cinone.getText().toString();

String fdate = pday + ". " + pmonth + ". " + pyear;

projectdatabase update = new projectdatabase(UpdateProject.this);
update.open();
update.updateProject(id, pname, fdate);
update.close();


}

}

Код для класса базы данных:

public class projectdatabase {

public static final String KEY_ROWID = "_id";
public static final String PROJECT_NAME = "project_name";
public static final String PROJECT_ID = "project_id";
public static final String PROJECT_DIFFICULTY = "project_difficulty";
public static final String PROJECT_STATUS = "project_status";
public static final String PROJECT_START_DATE = "project_start_date";
public static final String PROJECT_FINISH_DATE = "project_finsish_date";

private static final String DATABASE_NAME = "project_db";
static final String DATABASE_TABLE = "project_details";
private static final int DATABASE_VERSION = 1;

private DbHelper ourHelper;
private final Context projectdbContext;
private SQLiteDatabase projectDatabase;

private static class DbHelper extends SQLiteOpenHelper {
    public DbHelper(Context context) {

        super(context, DATABASE_NAME, null, DATABASE_VERSION);

    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // TODO Auto-generated method stub

        db.execSQL("CREATE TABLE "+ DATABASE_TABLE + " (" +
                KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                PROJECT_NAME + " TEXT NOT NULL, " +
                PROJECT_ID + " INTEGER, " +
                PROJECT_START_DATE + " TEXT, " +
                PROJECT_FINISH_DATE + " TEXT, " +
                PROJECT_DIFFICULTY + " TEXT, " +
                PROJECT_STATUS + " TEXT);"
               ); 

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO Auto-generated method stub

        db.execSQL("DROP TABLE IF EXIST " + DATABASE_NAME);
        onCreate(db);

    }
}

public projectdatabase (Context c) {                            
     projectdbContext = c;
}

public projectdatabase open() {                                                 //Open database
    ourHelper = new DbHelper(projectdbContext);
    projectDatabase = ourHelper.getWritableDatabase();
    return this;
}

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

public long createEntry(String name, String pid, String startdate, String finishdate, String difficulty, String Status) {           //Enter project data into database

    ContentValues cv = new ContentValues();
    cv.put(PROJECT_NAME, name);
    cv.put(PROJECT_ID, pid);
    cv.put(PROJECT_START_DATE, startdate);
    cv.put(PROJECT_FINISH_DATE, finishdate);
    cv.put(PROJECT_DIFFICULTY, difficulty);
    cv.put(PROJECT_STATUS, Status);

    return projectDatabase.insert(DATABASE_TABLE, null, cv);
}

public String getData() {                                                       //Retrieve all project data

    String[] columns = new String[] {KEY_ROWID, PROJECT_NAME, PROJECT_ID, PROJECT_START_DATE, PROJECT_FINISH_DATE, PROJECT_DIFFICULTY, PROJECT_STATUS};
    Cursor c = projectDatabase.query(DATABASE_TABLE, columns, null, null, null, null, null);
    String result = "";

    int iRow = c.getColumnIndex(KEY_ROWID);
    int iName = c.getColumnIndex(PROJECT_NAME);
    int iID = c.getColumnIndex(PROJECT_ID);
    int iStartDate = c.getColumnIndex(PROJECT_START_DATE);
    int iFinishDate = c.getColumnIndex(PROJECT_FINISH_DATE);
    int iDifficulty = c.getColumnIndex(PROJECT_DIFFICULTY);
    int iStatus = c.getColumnIndex(PROJECT_STATUS);

    for(c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {

        result = result + c.getString(iRow) + "|" + c.getString(iName) + "|" + c.getString(iID) + "|" + c.getString(iStartDate) + "|" + c.getString(iFinishDate) + "|" + c.getString(iDifficulty) + "|" + c.getString(iStatus) + "\n";

    }

    return result;
}

public Cursor getDataforDisplay () {                                            //Project data for list view

    String[] columns = new String[] {KEY_ROWID, PROJECT_NAME, PROJECT_FINISH_DATE, PROJECT_DIFFICULTY, PROJECT_STATUS};
    Cursor c = projectDatabase.query(DATABASE_TABLE, columns, null, null, null, null, null);

    c.moveToFirst();
    return c;

}

public String getProjectName(String id) {                   

    String[] columns = new String[] {PROJECT_NAME,KEY_ROWID};
    Cursor c = projectDatabase.query(DATABASE_TABLE, columns, KEY_ROWID + "=" + id, null, null, null, null);

    if(c != null) {

        int iName = c.getColumnIndex(PROJECT_NAME);

        c.moveToFirst();
        String name = c.getString(iName);
        return name;

    }

    return null;
}

общедоступная строка getProjectStatus (идентификатор строки) {

    String[] columns = new String[] {PROJECT_STATUS,KEY_ROWID};
    Cursor c = projectDatabase.query(DATABASE_TABLE, columns, KEY_ROWID + "=" + id, null, null, null, null);

    if(c != null) {

        int iStatus = c.getColumnIndex(PROJECT_STATUS);

        c.moveToFirst();
        String status = c.getString(iStatus);
        return status;

    }

    return null;
}

общедоступная строка getProjectDifficulty (идентификатор строки) {

String[] columns = new String[] {PROJECT_DIFFICULTY,KEY_ROWID};
Cursor c = projectDatabase.query(DATABASE_TABLE, columns, KEY_ROWID + "=" + id, null, null, null, null);

if(c != null) {

    int iDiff = c.getColumnIndex(PROJECT_DIFFICULTY);

    c.moveToFirst();
    String diff = c.getString(iDiff);
    return diff;

}

return null;

}

общедоступная строка getProjectstartdate (идентификатор строки) {

String[] columns = new String[] {PROJECT_START_DATE,KEY_ROWID};
Cursor c = projectDatabase.query(DATABASE_TABLE, columns, KEY_ROWID + "=" + id, null, null, null, null);

if(c != null) {

    int iSdate = c.getColumnIndex(PROJECT_START_DATE);

    c.moveToFirst();
    String sdate = c.getString(iSdate);
    return sdate;

}

return null;

}

общедоступная строка getProjectfinishdate (идентификатор строки) {

String[] columns = new String[] {PROJECT_FINISH_DATE,KEY_ROWID};
Cursor c = projectDatabase.query(DATABASE_TABLE, columns, KEY_ROWID + "=" + id, null, null, null, null);

if(c != null) {

    int iFdate = c.getColumnIndex(PROJECT_FINISH_DATE);

    c.moveToFirst();
    String fdate = c.getString(iFdate);
    return fdate;

}

return null;

}

public void updateProject(String id, String PName, String FDate) { // метод для обновления базы данных

ContentValues cvUpdate = new ContentValues();
cvUpdate.put(PROJECT_NAME, PName);
cvUpdate.put(PROJECT_FINISH_DATE, FDate);

projectDatabase.update(DATABASE_TABLE, cvUpdate, KEY_ROWID + "=" + id, null); 

}

}

EDIT: если я заменю метод updateProject() любым другим методом из класса базы данных, ошибка исчезнет, ​​и приложение запустится без проблем.


person krtkush    schedule 31.12.2012    source источник
comment
Чем отличается ваш драгоценный рабочий код?   -  person Robert Harvey    schedule 31.12.2012
comment
У этого не было рабочего фрагмента выбора даты. Вот и все. Остальной код был таким же. Я удалил это и переписал как новое действие, и теперь у меня возникла эта проблема.   -  person krtkush    schedule 31.12.2012
comment
Это единственное место, где вы открываете БД?   -  person Geobits    schedule 31.12.2012
comment
Бьюсь об заклад, если вы поместите два фрагмента кода рядом и просмотрите их построчно, вы увидите некоторые другие различия.   -  person Robert Harvey    schedule 31.12.2012
comment
@Geobits В этом упражнении да! @ RobertHarvey В том-то и проблема, что у меня больше нет этого кода!   -  person krtkush    schedule 31.12.2012
comment
Ах. Тогда вы говорите о несуществующем ранее существовавшем драгоценном коде.   -  person Robert Harvey    schedule 31.12.2012
comment
Убедитесь, что ВСЕ ваши КУРСОРЫ тоже закрыты.   -  person varevarao    schedule 31.12.2012
comment
@varevarao как мне это сделать?   -  person krtkush    schedule 31.12.2012
comment
Я предполагаю, что вы запускаете запрос к базе данных в своем методе updateProject(), этот запрос возвращает курсоры, которые также должны быть закрыты. Для каждого курсора, как только вы закончите со всеми данными, которые вам нужны от них, вызовите для них cursorName.close(). Вот ссылка на веб-сайте разработчиков.   -  person varevarao    schedule 31.12.2012
comment
@varevarao Я добавил определение метода в описание. Должен ли я добавить dbupdate.close() в конце определения??   -  person krtkush    schedule 31.12.2012
comment
Не могли бы вы добавить свой код класса для класса ProjectDatabase? Это действительно поможет понять проблему здесь.   -  person varevarao    schedule 31.12.2012
comment
@varevarao Я добавил базу данных, а также активность, пожалуйста, посмотрите!   -  person krtkush    schedule 31.12.2012


Ответы (2)


Вам нужно правильно спроектировать свой SQLiteOpenHelper класс. Многие гуру предлагают создать статическую ссылку, которая гарантирует, что в любой момент времени существует только один экземпляр DatabaseHelper.

Код ниже даст вам некоторое представление об этом. (Это не полный код, но даст вам подсказку)

public class DatabaseHelper extends SQLiteOpenHelper { 
    private static DatabaseHelper mDBHelper;

    public static DatabaseHelper getInstance(Context ctx) {

        if (mDBHelper == null) { //this will ensure no multiple instances out there.
            mDBHelper = new DatabaseHelper(ctx.getApplicationContext());
        }
        return mDBHelper;
    }

}

А теперь сделай трюк.

открыть базу данных

private SQLiteDatabase db;
    public synchronized SQLiteDatabase open() throws SQLException {

        if(db ==null){
            db = DBHelper.getWritableDatabase();
        }

        return db;
    }

Закройте базу данных.

public synchronized void close() {

        //do nothing. This is a trick.
    }

Причина: Для мобильного приложения нет необходимости в механизме открытия и закрытия. Это лучше всего подходит для веб-приложения, где несколько пользователей пытаются получить доступ к базе данных, но в случае мобильного приложения ваше приложение будет использовать только один пользователь.

Этот хак также гарантирует, что вы никогда не получите ошибку Close() was never explicitly called on database. Это исключение возникает, когда вы открыли больше экземпляров SQLiteDatabase, чем закрыли, и теперь в нашем случае есть только один экземпляр SQLiteDatabse. Это также решит проблему с одновременным доступом/записью базы данных.

Надеюсь, этот лайфхак поможет вам понять реальную проблему.

Для лучшего понимания вы можете перейти по этой ссылке. .

person Moin Ahmed    schedule 01.01.2013

public projectdatabase open() {
    ourHelper = new DbHelper(projectdbContext);
    projectDatabase = ourHelper.getWritableDatabase();
    return this;
}

public void close() {
    ourHelper.close();
}

Там вверху попробуйте изменить ourHelper.close() на projectDatabase.close(). Вы должны закрыть экземпляр WriteableDatabase SQLiteDatabase, который вы открыли. Не DBHelper.

Таким образом, ваша функция закрытия станет:

public void close() {
    projectDatabase.close();
}

[EDIT]: на сайте sqlite я нашел эту информацию. Причина, по которой это работает, когда вы заменяете updateProject() любым другим методом, заключается в том, что это единственный метод, при котором вы получаете блокировку записи в базе данных. Базы данных SQLite не имеют блокировки чтения, только блокировку записи.

Вы пытались вызвать закрытие базы данных проекта в конце вашего метода updateProject() (внутри него)?

Еще одно мое предложение — сделать ваш класс базы данных одноэлементным. Это позволит избежать любых конфликтов, поскольку в любой момент времени к базе данных будет обращаться только один объект.

person varevarao    schedule 31.12.2012
comment
Я реализовал это. Ошибка исчезла! Благодарность! Но теперь моя база данных не обновляется. - person krtkush; 31.12.2012