2014-01-15 46 views
1

這個問題已被問過多次,我想我的情況有點不同。關閉從未明確呼籲數據庫

早些時候 我聲明在類級別我的數據庫對象:

DBAdapter dbHelper; 
中的onCreate

dbHelper = new DBAdapter(this); 

我已經關閉了DB在破壞:

@Override 
    public void onDestroy(){ 
     super.onDestroy(); 
     if (dbHelper != null) 
     { 
      dbHelper.close(); 
     } 

    } 

但是,每次寫入數據庫時​​都會發生錯誤。關閉之後從未明確地調用過數據庫它對數據庫鎖定也有一些例外。

的問題

我有一個異步任務,在此我更新三個表爲其他後每條記錄。 (操作確實很大)但是現在我將DB init的代碼轉換爲我的異步任務。在預執行我初始化數據庫,然後我關閉數據庫在onPostExecute。然而,問題仍然存在,可以解決這個問題呢?下面是我的異步任務的代碼:

private class MagicCall extends AsyncTask<Void, String, String> { 

     int years; 
     long secon; 
     long min; 
     int hours; 
     int mon; 
     int days; 
     int weeks; 
     String CONTACT_ID,CONTACT_NAME,CONTACT_IMAGE_URI; 

     ProgressDialog Asycdialog = new ProgressDialog(LoaderClass.this); 

     @Override 
     protected void onPreExecute() { 
      dbHelper = new DBAdapter(getApplicationContext()); 
      dbHelper.open(); 
      //Init the LoaderDialog 
      Asycdialog.setMessage("Working"); 
      Asycdialog.getWindow().setGravity(Gravity.CENTER_VERTICAL); 
      Asycdialog.getWindow().setGravity(Gravity.CENTER_HORIZONTAL); 
      Asycdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 
      Asycdialog.setCancelable(false); 
      //Dialog Show 
      Asycdialog.show(); 
      super.onPreExecute(); 
     } 

     protected void onPostExecute(String result) { 
      // hide the dialog 
      dbHelper.close(); 
      Asycdialog.dismiss(); 
      startActivity(new Intent(LoaderClass.this, MainActivity.class)); 
      finish(); 
      super.onPostExecute(result); 
     } 

     @Override 
     protected String doInBackground(Void... args) { 


      // 
      // Dear maintainer: 
      // 
      // Once you are done trying to 'optimise' this routine, 
      // and have realized what a terrible mistake that was, 
      // please increment the following counter as a warning 
      // to the next guy: 
      // 
      // total_hours_wasted_here = 0; 
      // 
      int lines = 0; 
      try{ 
       BufferedReader reader; 
       if(FLAG ==1){ 
        reader = new BufferedReader(new FileReader("/sdcard/BirthdayReminders/fileone.txt")); 
       }else{ 
        reader = new BufferedReader(new FileReader("/sdcard/BirthdayReminders/output.txt")); 
       } 
       while (reader.readLine() != null) lines++; 
       reader.close(); 
      }catch(Exception e){ 

      } 



      dbHelper.NotificationDrop(); 
      int i=0; 
      File toRead = null; 
      try{ 
       if(FLAG ==1){ 
        toRead=new File("/sdcard/BirthdayReminders/fileone.txt"); 
       }else{ 
        toRead=new File("/sdcard/BirthdayReminders/output.txt"); 
       } 
       FileInputStream fis=new FileInputStream(toRead); 

       Scanner sc=new Scanner(fis); 

       //read data from file line by line: 
       String currentLine; 
       while(sc.hasNextLine()){ 


        currentLine=sc.nextLine(); 
        //now tokenize the currentLine: 
        StringTokenizer st=new StringTokenizer(currentLine,"=",false); 
        //put tokens ot currentLine in map 
        // mapInFile.put(st.nextToken(),st.nextToken()); 

        String dateStr = st.nextToken(); 
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 
        Date date = format.parse(dateStr); 
        java.sql.Date dx = new java.sql.Date(date.getTime()); 
        Date key = dx; 
        String dateToInsert = String.valueOf(dx); 
        // ********* 
        String listStr = st.nextToken(); 

        String cut = listStr.substring(1, listStr.length() - 1); 

        String[] array = cut.split(","); 
        CONTACT_ID = (array[0].trim()); 

        CONTACT_NAME = toTitleCase(array[1].trim()); 

        if(array[2].contains(".jp")) 
         array[2] = array[2].replace(".jp", ".jpg").trim(); 
        CONTACT_IMAGE_URI = (array[2].trim()); 


        if (isCancelled()) { 
         break; 
        } 
        // int k = Sx.size(); 


        String progress = ("" + Character.toUpperCase(CONTACT_NAME.charAt(0)) + CONTACT_NAME.substring(1) + "\n"+i + " of " + lines + " Contacts"); // Progress displayed here. 



        years = getDiffYear(key);    // For years elapsed 
        secon = seconds(key);     // for seconds elapsed 
        min = seconds(key)/60;    // For minutes elapsed 
        hours = (int) (seconds(key)/60)/60; // For hours elapsed 
        mon = months(String.valueOf(key));      // for months elapsed 

        days = daysElapsed(key);    // Days elapsed 
        weeks = daysElapsed(key)/7;   // For weeks 

        //=============================================================================================================== 
        if (dateToInsert.contains("0001-") == true){ //Special Case, we added 0001 to Birthdays Which Have NO Year field. 
         //=========================================================================================================== 

         dbHelper.insert(dateToInsert, CONTACT_NAME, "","", CONTACT_IMAGE_URI, "", "", "", CONTACT_ID, "", ""); // All other fields will be empty, because we don't have a Year. 
         int PRIMARY_ID = dbHelper.getPrimaryId(); 
         String FOREIGN_KEY = dbHelper.getHighestID(PRIMARY_ID); 


         //===================================================================================================== 
         //In this case we are only interested in fetching the year alert for next birthday of this contact --> 
         //===================================================================================================== 

         intCal.yearsToNotify(years, dateToInsert); 
         int yearsSpecial = intCal.getYearsRegular(); 
         Date dateYearsReg = intCal.getYearsRegDate(); 

         dbHelper.insertNotifications(5, convertDate(dateYearsReg), 0, yearsSpecial,FOREIGN_KEY,PRIMARY_ID); 

        } 
        //========================================================================= 
        //Case when all the Date fields exist and we set up notifications ---> 
        //========================================================================= 
        else if(dateToInsert != "null" && dateToInsert.contains("0001-") != true){ 

         dbHelper.insert(dateToInsert, CONTACT_NAME, String.valueOf(days), String.valueOf(hours), CONTACT_IMAGE_URI, String.valueOf(min),String.valueOf(mon), String.valueOf(secon), CONTACT_ID, String.valueOf(weeks), String.valueOf(years)); 

         int PRIMARY_ID = dbHelper.getPrimaryId(); // Fetch the PrimaryId (_id) of the above inserted row, its the Foreign key for Notification and SpecialNotifications Table. 
         String FOREIGN_KEY = dbHelper.getHighestID(PRIMARY_ID); // Same as above, but fetches the Name field of the last inserted row. 



         //========================================================================= 
         //**Database Insertions Notifications Table/ SpecialNotifications Table** 
         //========================================================================= 



         //=======================================================================================// 
         //Regular intervals DB Insertions: 
         //======================================================================================// 
         //Notification Types: 
         //1 for months 
         //2 for weeks 
         //3 for days 
         //4 for minutes 
         //5 for years 
         //6 for seconds 
         //7 for hours 
         //======================================================================================// 

         //============================== 
         //For Months 
         //============================== 
         intCal.monthsNotify(mon, dateToInsert); 
         int monSpecial = intCal.getMonthRegular(); 
         Date dateMonReg = intCal.getMonRegDate(); 


         dbHelper.insertNotifications(1, convertDate(dateMonReg), 0, monSpecial,FOREIGN_KEY,PRIMARY_ID); 


         //=============================== 
         //For Weeks 
         //=============================== 
         intCal.weeksToNotify(weeks,dateToInsert); 
         int weekSpecial = intCal.getWeekRegular(); 
         Date dateWeekReg =intCal.getWeekRegDate(); 

         dbHelper.insertNotifications(2, convertDate(dateWeekReg), 0, weekSpecial,FOREIGN_KEY,PRIMARY_ID); 


         //=============================== 
         //For Days 
         //=============================== 
         intCal.daysToNotify(days, dateToInsert); 
         int daysSpecial= intCal.getDaysRegular(); 
         Date dateDaysReg = intCal.getDaysRegDate(); 

         dbHelper.insertNotifications(3, convertDate(dateDaysReg), 0, daysSpecial,FOREIGN_KEY,PRIMARY_ID); 


         //=============================== 
         //For minutes 
         //=============================== 
         intCal.minutesToNotify(min,dateToInsert); 
         long minutesSpecial= intCal.getMinutesRegular(); 
         Date dateMinsReg = intCal.getMinutesRegDate(); 

         dbHelper.insertNotifications(4, convertDate(dateMinsReg), 0,(int) minutesSpecial,FOREIGN_KEY,PRIMARY_ID); 


         //============================== 
         //For Years 
         //============================== 
         intCal.yearsToNotify(years, dateToInsert); 
         int yearsSpecial = intCal.getYearsRegular(); 
         Date dateYearsReg = intCal.getYearsRegDate(); 

         dbHelper.insertNotifications(5, convertDate(dateYearsReg), 0, yearsSpecial,FOREIGN_KEY,PRIMARY_ID); 


         //============================= 
         //For Seconds 
         //============================= 
         intCal.secondsToNotify(secon, dateToInsert); 
         long secondsSpecial= intCal.getSecondsRegular(); 
         Date dateSecondsReg = intCal.getSecondsRegDate(); 

         dbHelper.insertNotifications(6, convertDate(dateSecondsReg), 0, secondsSpecial,FOREIGN_KEY,PRIMARY_ID); 


         //============================= 
         //For Hours 
         //============================= 
         intCal.hoursToNotify(hours, dateToInsert); 
         int hoursSpecial= intCal.getHoursRegular(); 
         Date dateHoursReg= intCal.getHoursRegDate(); 

         dbHelper.insertNotifications(7, convertDate(dateHoursReg), 0, hoursSpecial,FOREIGN_KEY,PRIMARY_ID); 



         //============================================================================================// 
         //Special Intervals 
         //=============================================================================================================// 
         //Notification Types: 
         //1 for months 
         //2 for weeks 
         //3 for days 
         //4 for minutes 
         //5 for years 
         //6 for seconds 
         //7 for hours 
         //For Years 
         intCal.specialIntervalYears(years, dateToInsert); 
         int yearsOnceSpecial =intCal.getYearsSpecial(); 
         Date dateYearsSpecial = intCal.getYearsSpDate(); 
         dbHelper.insertSpecialNotifications(5, convertDate(dateYearsSpecial), yearsOnceSpecial,FOREIGN_KEY,PRIMARY_ID); 


         //For Months 
         intCal.specialIntervalMonths(mon,dateToInsert); 
         int monthsOnceSpecial= intCal.getMonthsSpecial(); 
         Date dateMonthsSpecial = intCal.getMonthsSpDate(); 
         dbHelper.insertSpecialNotifications(1, convertDate(dateMonthsSpecial), monthsOnceSpecial,FOREIGN_KEY,PRIMARY_ID); 


         //For Weeks 
         intCal.specialIntervalsWeeks(weeks,dateToInsert); 
         int weeksOnceSpecial= intCal.getWeeksSpecial(); 
         Date dateWeeksSpecial = intCal.getWeeksSpDate(); 
         dbHelper.insertSpecialNotifications(2, convertDate(dateWeeksSpecial), weeksOnceSpecial,FOREIGN_KEY,PRIMARY_ID); 

         //For Days 
         intCal.specialIntervalsDays(days, dateToInsert); 
         int daysOnceSpecial= intCal.getDaysSpecial(); 
         Date dateDaysSpecial = intCal.getDaysSpDate(); 
         dbHelper.insertSpecialNotifications(3, convertDate(dateDaysSpecial), daysOnceSpecial,FOREIGN_KEY,PRIMARY_ID); 

         //For Hours 
         intCal.specialIntervalsHours(hours,dateToInsert); 
         int hoursOnceSpecial= intCal.getHoursSpecial(); 
         Date dateHoursSpecial = intCal.getHoursSpDate(); 
         dbHelper.insertSpecialNotifications(7, convertDate(dateHoursSpecial), hoursOnceSpecial,FOREIGN_KEY,PRIMARY_ID); 

         //For Minutes 
         intCal.specialIntervalMinutes(min,dateToInsert); 
         long minutesOnceSpecial= intCal.getMinutesSpecial(); 
         Date dateMinutesSpecial= intCal.getMinutesSpDate(); 
         dbHelper.insertSpecialNotifications(4, convertDate(dateMinutesSpecial), (int)minutesOnceSpecial,FOREIGN_KEY,PRIMARY_ID); 

         //For Seconds 
         intCal.specialIntervalsSeconds(secon,dateToInsert); 
         long secondsOnceSpecial= intCal.getSecondsSpecial(); 
         Date dateSecondsSpecial= intCal.getSecondsSpDate(); 
         dbHelper.insertSpecialNotifications(6, convertDate(dateSecondsSpecial), secondsOnceSpecial,FOREIGN_KEY,PRIMARY_ID); 

        } 
        publishProgress(progress); 
        Asycdialog.setMax(lines); 
        Asycdialog.incrementProgressBy(1); 
        i++; 
       } 

      }catch (Exception e){ 

      } 
      try{ 
       writeToSD(); 
      }catch (Exception e){ 
       System.out.println(""+e); 
      } 


      return ""; 

     } 

     protected void onProgressUpdate(String... values) { 

      super.onProgressUpdate(values); 
      Asycdialog.setMessage("" + values[0]); 
     } 


    } 

這裏是日誌:

01-15 09:22:36.215: E/SQLiteDatabase(728): close() was never explicitly called on database '/data/data/com.exa.birthdayrem/databases/Bdr' 
01-15 09:22:36.215: E/SQLiteDatabase(728): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1943) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1007) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:986) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1051) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:770) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:157) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at com.exa.birthdayrem.DBAdapter.<init>(DBAdapter.java:110) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at com.exa.birthdayrem.LoaderClass$MagicCall.onPreExecute(LoaderClass.java:378) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:561) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.os.AsyncTask.execute(AsyncTask.java:511) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at com.exa.birthdayrem.LoaderClass.onLoadFinished(LoaderClass.java:225) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at com.exa.birthdayrem.LoaderClass.onLoadFinished(LoaderClass.java:1) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:433) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(LoaderManager.java:405) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.content.Loader.deliverResult(Loader.java:110) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.content.CursorLoader.deliverResult(CursorLoader.java:88) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.content.CursorLoader.deliverResult(CursorLoader.java:42) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.content.AsyncTaskLoader.dispatchOnLoadComplete(AsyncTaskLoader.java:236) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.content.AsyncTaskLoader$LoadTask.onPostExecute(AsyncTaskLoader.java:76) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.os.AsyncTask.finish(AsyncTask.java:602) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.os.AsyncTask.access$600(AsyncTask.java:156) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.os.Handler.dispatchMessage(Handler.java:99) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.os.Looper.loop(Looper.java:137) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at android.app.ActivityThread.main(ActivityThread.java:4340) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at java.lang.reflect.Method.invokeNative(Native Method) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at java.lang.reflect.Method.invoke(Method.java:511) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
01-15 09:22:36.215: E/SQLiteDatabase(728): at dalvik.system.NativeStart.main(Native Method) 
01-15 09:22:36.215: E/System(728): Uncaught exception thrown by finalizer 
01-15 09:22:36.235: E/System(728): java.lang.IllegalStateException: Don't have database lock! 
01-15 09:22:36.235: E/System(728): at android.database.sqlite.SQLiteDatabase.verifyLockOwner(SQLiteDatabase.java:2090) 
01-15 09:22:36.235: E/System(728): at android.database.sqlite.SQLiteDatabase$1.entryRemoved(SQLiteDatabase.java:2182) 
01-15 09:22:36.235: E/System(728): at android.database.sqlite.SQLiteDatabase$1.entryRemoved(SQLiteDatabase.java:2178) 
01-15 09:22:36.235: E/System(728): at android.util.LruCache.trimToSize(LruCache.java:197) 
01-15 09:22:36.235: E/System(728): at android.util.LruCache.evictAll(LruCache.java:285) 
01-15 09:22:36.235: E/System(728): at android.database.sqlite.SQLiteDatabase.deallocCachedSqlStatements(SQLiteDatabase.java:2143) 
01-15 09:22:36.235: E/System(728): at android.database.sqlite.SQLiteDatabase.closeClosable(SQLiteDatabase.java:1126) 
01-15 09:22:36.235: E/System(728): at android.database.sqlite.SQLiteDatabase.finalize(SQLiteDatabase.java:1914) 
01-15 09:22:36.235: E/System(728): at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:182) 
01-15 09:22:36.235: E/System(728): at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:168) 
01-15 09:22:36.235: E/System(728): at java.lang.Thread.run(Thread.java:856) 

open方法中將對DBAdapter:

public DBAdapter open() throws SQLException { 
    DBHelper = new DatabaseHelper(mCtx); 
    mDb = DBHelper.getWritableDatabase(); 
    return this; 

} 
+0

請給一些日誌,它可以被調查! –

+0

好心地發佈'DBAdapter'類的open()方法的代碼 –

+0

完成後,請檢查一下! – Skynet

回答

1

我平時關閉分貝的finally塊爲每種方法。像下面

try { 
    //open db 
    // perform tasks 
} catch (Exception e) { 
    // handle exceptions 
} finally { 
    // close db 
} 
+0

我會試一試 – Skynet

+0

打開數據庫是一個昂貴的操作,所以這不是非常有效 – eski

1

這是最簡單的,以保持在全球範圍內的數據庫,無論是作爲一個靜態的或在您的應用程序類(由getApplicationContext()訪問),這樣,它永遠是開放的,而你的應用程序運行。

您還應該確保您使用數據庫的所有幫助程序方法都已正確同步。

你並不真的需要由工程師之一關閉數據庫,看到這個帖子:

https://groups.google.com/forum/#!msg/android-developers/nopkaw4UZ9U/cPfPL3uW7nQJ

「由於設計,保持什麼開放進程的生活的整個過程和從來沒有關閉它不是一個泄漏,它將在清理過程中被清除。「

+0

你可以通過保持全局上下文來闡述你的意思嗎?做單身? – Skynet

+0

Singleton/static可以工作,但在android上我更喜歡擴展Application類,並將其放在那裏。 它保證它會在你能做任何事情之前被創建,並且只要應用程序的流程存在就會存在。只記得在清單中聲明它。 – eski

+0

您還可以通過getApplicationContext從任何上下文訪問應用程序類,您只需將其轉換爲您的子類版本即可。 – eski