Close() tidak pernah dipanggil secara eksplisit pada database bahkan setelah mengimplementasikan close()

Eclipse menunjukkan kepada saya kesalahan di atas meskipun saya telah menerapkan metode tersebut close().

Ini kodenya:

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();

}

Logcat:

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)

Hal yang aneh adalah saya telah menggunakan kode serupa dengan sangat baik dan berfungsi dengan sempurna. Selain itu, metode lain dari kelas database yang sama berfungsi dengan baik.

Kode aktivitas yang memanggil 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();


}

}

Kode untuk kelas database:

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

String publik getProjectStatus(String id) {

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

String publik getProjectDifficulty(String id) {

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;

}

String publik getProjectstartdate(String id) {

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;

}

public String getProjectfinishdate(String id) {

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) {//metode untuk mengupdate database

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: Jika saya mengganti metode updateProject() dengan metode lain dari kelas database, kesalahannya hilang dan aplikasi berjalan tanpa masalah.


person krtkush    schedule 31.12.2012    source sumber
comment
Apa yang berbeda dengan kode kerja Anda yang berharga?   -  person Robert Harvey    schedule 31.12.2012
comment
Yang itu tidak memiliki fragmen pemilih Tanggal yang berfungsi. Itu dia. Kode lainnya sama. Saya menghapusnya dan menulis ulang sebagai aktivitas baru dan sekarang saya mendapatkan masalah ini.   -  person krtkush    schedule 31.12.2012
comment
Apakah ini satu-satunya tempat Anda membuka db?   -  person Geobits    schedule 31.12.2012
comment
Saya yakin jika Anda meletakkan kedua potongan kode tersebut secara berdampingan dan melihatnya baris demi baris, Anda akan melihat beberapa perbedaan lainnya.   -  person Robert Harvey    schedule 31.12.2012
comment
@Geobits Dalam kegiatan ini ya! @ RobertHarvey Itu masalahnya, saya tidak punya kode itu lagi!   -  person krtkush    schedule 31.12.2012
comment
Ah. Maka Anda sedang berbicara tentang kode berharga yang sudah ada sebelumnya dan tidak ada.   -  person Robert Harvey    schedule 31.12.2012
comment
Periksa apakah SEMUA KURSOR Anda juga ditutup.   -  person varevarao    schedule 31.12.2012
comment
@varevarao bagaimana cara melakukannya?   -  person krtkush    schedule 31.12.2012
comment
Saya berasumsi Anda menjalankan kueri pada Db dalam metode updateProject() Anda, kueri ini mengembalikan Kursor yang juga harus ditutup. Untuk setiap Cursor, setelah Anda selesai dengan semua data yang Anda perlukan, panggil kursorName.close() pada kursor tersebut. Berikut referensi di situs web pengembang.   -  person varevarao    schedule 31.12.2012
comment
@varevarao Saya telah menambahkan definisi metode dalam deskripsi. Haruskah saya menambahkan dbupdate.close() di akhir definisi??   -  person krtkush    schedule 31.12.2012
comment
Bisakah Anda menambahkan kode Kelas Anda untuk kelas ProjectDatabase? Itu akan sangat membantu memahami masalah di sini.   -  person varevarao    schedule 31.12.2012
comment
@varevarao Saya telah menambahkan database serta aktivitasnya, silakan lihat!   -  person krtkush    schedule 31.12.2012


Jawaban (2)


Anda perlu mendesain kelas SQLiteOpenHelper Anda dengan benar. Banyak guru menyarankan untuk membuat referensi statis yang akan memastikan bahwa hanya ada satu instance DatabaseHelper setiap saat.

Kode di bawah ini akan memberi Anda gambaran tentangnya. (Ini bukan kode lengkap tetapi akan memberi Anda beberapa petunjuk)

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

}

Sekarang, lakukan sebuah trik.

buka basis data

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

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

        return db;
    }

Tutup basis data.

public synchronized void close() {

        //do nothing. This is a trick.
    }

Alasan : Untuk aplikasi mobile, tidak diperlukan mekanisme buka dan tutup. Ini paling cocok untuk aplikasi Web di mana banyak pengguna mencoba mengakses db tetapi dalam kasus aplikasi seluler, hanya satu pengguna yang akan menggunakan aplikasi Anda.

Peretasan ini juga akan memastikan bahwa Anda tidak akan pernah mendapatkan kesalahan Close() was never explicitly called on database. Pengecualian ini terjadi ketika Anda membuka lebih banyak instance SQLiteDatabase daripada yang Anda tutup dan sekarang dalam kasus kami hanya ada satu instance SQLiteDatabse. Ini juga akan menangani masalah akses/penulisan db secara bersamaan.

Semoga peretasan ini akan membantu Anda memahami masalah sebenarnya.

Untuk pemahaman yang lebih baik, Anda dapat merujuk tautan ini .

person Moin Ahmed    schedule 01.01.2013

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

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

Di atas sana, coba ubah ourHelper.close() menjadi projectDatabase.close(). Anda harus menutup instance WriteableDatabase SQLiteDatabase yang Anda buka. Bukan DBHelper.

Jadi fungsi close Anda akan menjadi:

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

[EDIT]: Dari situs sqlite saya menemukan info ini. Alasannya berhasil ketika Anda mengganti updateProject() dengan metode lain adalah karena itulah satu-satunya metode di mana Anda mendapatkan kunci tulis pada database. Database SQLite tidak memiliki kunci baca, hanya kunci tulis.

Sudahkah Anda mencoba memanggil penutupan projectDatabase di akhir metode updateProject() Anda (di dalamnya)?

Saran lain yang akan saya berikan adalah menjadikan kelas Database Anda tunggal. Ini akan menghindari konflik karena hanya ada satu objek yang mengakses db pada waktu tertentu.

person varevarao    schedule 31.12.2012
comment
Saya menerapkan ini. Kesalahannya hilang! terima kasih! Tapi sekarang database saya tidak diperbarui. - person krtkush; 31.12.2012