Jika Anda mendapatkan pesan yang menunjukkan terlalu banyak file yang dibuka, penyebabnya mungkin karena terlalu banyak kursor yang masih terbuka.
Namun, pesan yang dikembalikan mungkin tidak selalu sama dan mungkin khusus untuk tugas/panggilan yang dipanggil.
Dalam hal ini pesannya adalah (unable to open database file (code 2062))
, namun dalam kasus lain (dari SELECT pesannya adalah unable to open database file (code 14)
). SQLite tidak dapat membuka file database (kode 14) pada kueri “SELECT” yang sering.
Tautan di atas juga menunjuk ke posting yang saya buat yang dengan jelas menunjukkan bahwa membuat Cursor menghasilkan file (atau file) yang dibuka.
Contohnya adalah perulangan sekitar 500 baris dan untuk setiap baris itu membuat/membuat ulang 3 kursor untuk setiap baris (jadi berpotensi 1500+ kursor meskipun hanya menggunakan 4 objek kursor).
Awalnya hanya menutup 3 kursor di akhir (baris terakhir dari induk semua) mengakibatkan unable to open database File (code 14)
. Menutup 3 kursor untuk setiap iterasi menyelesaikan masalah.
Kode yang gagal adalah :-
SQLiteDatabase db = getWritableDatabase();
Cursor shoplistcursor = getAllRowsFromTable(SHOPLIST_TABLE_NAME);
Cursor productcsr;
Cursor aislecsr;
Cursor prdusecsr;
while(shoplistcursor.moveToNext()) {
productcsr = getProductFromProductId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
aislecsr = getAisleFromAisleId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)));
prdusecsr = getProductUsage(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)),
shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
if (productcsr.getCount() < 1 | aislecsr.getCount() < 1 | prdusecsr.getCount() < 1) {
deleteShopListEntry(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_ID)));
}
if(shoplistcursor.isLast()) {
prdusecsr.close();
aislecsr.close();
productcsr.close();
}
}
shoplistcursor.close();
db.close();
}
Sedangkan kode tetapnya adalah :-
SQLiteDatabase db = getWritableDatabase();
Cursor shoplistcursor = getAllRowsFromTable(SHOPLIST_TABLE_NAME);
Cursor productcsr;
Cursor aislecsr;
Cursor prdusecsr;
while(shoplistcursor.moveToNext()) {
productcsr = getProductFromProductId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
aislecsr = getAisleFromAisleId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)));
prdusecsr = getProductUsage(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)),
shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
if (productcsr.getCount() < 1 | aislecsr.getCount() < 1 | prdusecsr.getCount() < 1) {
productcsr.close();
aislecsr.close();
prdusecsr.close();
deleteShopListEntry(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_ID)));
} else {
productcsr.close();
aislecsr.close();
prdusecsr.close();
}
}
shoplistcursor.close();
db.close();
}
Saya sekarang cenderung mengikuti aturan/praktik berikut :-
-
Jika hanya mendapatkan hasil mis. mendapatkan jumlah baris, tutup Kursor dalam metode.
-
Jika menggunakan Kursor untuk tampilan mis. ListView, lalu tutup kursor di
onDestroy
aktivitas metode. -
Jika menggunakan Kursor untuk apa yang saya sebut pemrosesan yang lebih kompleks, mis. menghapus baris dengan referensi yang mendasarinya, lalu tutup kursor segera setelah selesai, dalam loop pemrosesan.