2010-08-25 165 views
3

我有一個SQLiteDatabase數據成員,我在onCreate中初始化並在onPause(),onStop()和onDestroy()上調用.close()。它在onResume()中重新初始化。它似乎運行得很好,但是當我看着調試器就看到這一點:Android認爲我沒有關閉我的數據庫!爲什麼?

08-24 20:23:50.014: ERROR/Database(6767): Leak found 
08-24 20:23:50.014: ERROR/Database(6767): java.lang.IllegalStateException: /data/data/com.hh.Timepunch/databases/times_database.db SQLiteDatabase created and never closed 
08-24 20:23:50.014: ERROR/Database(6767):  at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1695) 
08-24 20:23:50.014: ERROR/Database(6767):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:739) 
08-24 20:23:50.014: ERROR/Database(6767):  at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:761) 
08-24 20:23:50.014: ERROR/Database(6767):  at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:754) 
08-24 20:23:50.014: ERROR/Database(6767):  at android.app.ApplicationContext.openOrCreateDatabase(ApplicationContext.java:476) 
08-24 20:23:50.014: ERROR/Database(6767):  at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:193) 
08-24 20:23:50.014: ERROR/Database(6767):  at com.hh.Timepunch.TimeSheetActivity.onCreate(TimeSheetActivity.java:72) 
08-24 20:23:50.014: ERROR/Database(6767):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 
08-24 20:23:50.014: ERROR/Database(6767):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459) 
08-24 20:23:50.014: ERROR/Database(6767):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512) 
08-24 20:23:50.014: ERROR/Database(6767):  at android.app.ActivityThread.access$2200(ActivityThread.java:119) 
08-24 20:23:50.014: ERROR/Database(6767):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863) 
08-24 20:23:50.014: ERROR/Database(6767):  at android.os.Handler.dispatchMessage(Handler.java:99) 
08-24 20:23:50.014: ERROR/Database(6767):  at android.os.Looper.loop(Looper.java:123) 
08-24 20:23:50.014: ERROR/Database(6767):  at android.app.ActivityThread.main(ActivityThread.java:4363) 
08-24 20:23:50.014: ERROR/Database(6767):  at java.lang.reflect.Method.invokeNative(Native Method) 
08-24 20:23:50.014: ERROR/Database(6767):  at java.lang.reflect.Method.invoke(Method.java:521) 
08-24 20:23:50.014: ERROR/Database(6767):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
08-24 20:23:50.014: ERROR/Database(6767):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
08-24 20:23:50.014: ERROR/Database(6767):  at dalvik.system.NativeStart.main(Native Method) 
08-24 20:23:50.054: ERROR/Database(6767): Leak found 
08-24 20:23:50.054: ERROR/Database(6767): java.lang.IllegalStateException: /data/data/com.hh.Timepunch/databases/times_database.db SQLiteDatabase created and never closed 
08-24 20:23:50.054: ERROR/Database(6767):  at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1695) 
08-24 20:23:50.054: ERROR/Database(6767):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:739) 
08-24 20:23:50.054: ERROR/Database(6767):  at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:761) 
08-24 20:23:50.054: ERROR/Database(6767):  at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:754) 
08-24 20:23:50.054: ERROR/Database(6767):  at android.app.ApplicationContext.openOrCreateDatabase(ApplicationContext.java:476) 
08-24 20:23:50.054: ERROR/Database(6767):  at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:193) 
08-24 20:23:50.054: ERROR/Database(6767):  at com.hh.Timepunch.TimepunchActivity.onCreate(TimepunchActivity.java:60) 
08-24 20:23:50.054: ERROR/Database(6767):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 
08-24 20:23:50.054: ERROR/Database(6767):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459) 
08-24 20:23:50.054: ERROR/Database(6767):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512) 
08-24 20:23:50.054: ERROR/Database(6767):  at android.app.ActivityThread.access$2200(ActivityThread.java:119) 
08-24 20:23:50.054: ERROR/Database(6767):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863) 
08-24 20:23:50.054: ERROR/Database(6767):  at android.os.Handler.dispatchMessage(Handler.java:99) 
08-24 20:23:50.054: ERROR/Database(6767):  at android.os.Looper.loop(Looper.java:123) 
08-24 20:23:50.054: ERROR/Database(6767):  at android.app.ActivityThread.main(ActivityThread.java:4363) 
08-24 20:23:50.054: ERROR/Database(6767):  at java.lang.reflect.Method.invokeNative(Native Method) 
08-24 20:23:50.054: ERROR/Database(6767):  at java.lang.reflect.Method.invoke(Method.java:521) 
08-24 20:23:50.054: ERROR/Database(6767):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
08-24 20:23:50.054: ERROR/Database(6767):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
08-24 20:23:50.054: ERROR/Database(6767):  at dalvik.system.NativeStart.main(Native Method) 
08-24 20:23:50.199: ERROR/libs3c2drender(1912): int S3c2DRender::DoG2D(unsigned int, s3c_img*, s3c_rect*, unsigned int, s3c_img*, s3c_rect*, int, int)::S3C_G2D_ROTATOR_18176 fail 

其中一個地方,我得到這個錯誤會從這個活動離開時的:

public class TimepunchActivity extends Activity { 

     Calendar timeNow = Calendar.getInstance(); 
     SQLiteDatabase timesDatabase; 

     @Override 
     public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.timepunch); 

      //Create/open and configure database (if necessary) 
      timesDatabase = openOrCreateDatabase(
        "times_database.db", 
        SQLiteDatabase.CREATE_IF_NECESSARY, 
        null); 
      timesDatabase.setLocale(Locale.getDefault()); 
      timesDatabase.setLockingEnabled(false); 
      timesDatabase.setVersion(3); 

      //lenient is set to true so incrementing minute 59 auto increments hour, etc 
      timeNow.setLenient(true); 

      //Create table (if necessary) 
      final String dbCommand = "CREATE TABLE IF NOT EXISTS Timepunches (punch INTEGER PRIMARY KEY);"; 
      timesDatabase.execSQL(dbCommand); 

      updateLastInPunch(); 

      Button punchButton = (Button)findViewById(R.id.punch_button); 
      punchButton.setHapticFeedbackEnabled(true); 
      punchButton.setOnClickListener(new View.OnClickListener() { 
       public void onClick(View v) { 
        //Insert data 
        ContentValues punchValue = new ContentValues(); 
        punchValue.put("punch", timeNow.getTimeInMillis()); 
        long newPunchID = timesDatabase.insert("Timepunches", null, punchValue); 
        punchValue.clear(); 

        //if punch already exists 
        if (newPunchID < 0) { 
         AlertDialog.Builder builder = new AlertDialog.Builder(TimepunchActivity.this); 
         builder.setTitle("Whoops") 
          .setMessage("I've already recorded a punch for this time and day.") 
          .setCancelable(true) 
          .setNeutralButton("Oh", new DialogInterface.OnClickListener() { 
           public void onClick(DialogInterface dialog, int id) { 
            dialog.cancel(); 
           } 
          }) 
          .show(); 
        } 
        else { 
        } 
       } //end setOnClick() 
      }); //end click listener for punchButton 
     } //end onCreate() 



     @Override 
     public void onResume() { 
      super.onResume(); 
      checkFirstTimer(); 

      //Open and configure database 
      timesDatabase = openOrCreateDatabase(
        "times_database.db", 
        SQLiteDatabase.CREATE_IF_NECESSARY, 
        null); 
      timesDatabase.setLocale(Locale.getDefault()); 
      timesDatabase.setLockingEnabled(false); 
      timesDatabase.setVersion(3); 


      //Update date object for current time 
      timeNow.setTimeInMillis(System.currentTimeMillis()); 
      timeNow.set(Calendar.SECOND, 0); 
      timeNow.set(Calendar.MILLISECOND, 0); 
      updateClock((TextView)findViewById(R.id.current_time_textbox), timeNow); 

      updateLastInPunch(); 
     } //end onResume() 


     @Override 
     public void onPause() { 
      super.onPause(); 
      timesDatabase.close(); 
     } //end onResume() 

     @Override 
     public void onStop() { 
      super.onStop(); 
      timesDatabase.close(); 
     } //end onResume() 

     @Override 
     public void onDestroy() { 
      super.onDestroy(); 
      timesDatabase.close(); 
     } //end onResume() 



     //Shows last in-punch that has no out-punch 
     // if there is none it hides the section 
     public void updateLastInPunch() { 
      Cursor punchCursor = timesDatabase.query("Timepunches", null, null, null, null, null, "punch ASC;"); 

      TextView inPunchLabel = (TextView)findViewById(R.id.in_punch_label_textview); 
      TextView inPunchTV = (TextView)findViewById(R.id.in_punch_time_textview); 

      //odd count means there is a missing punch (assumed to be latest in punch) 
      // therefore show last in punch 
      if ((punchCursor.getCount()%2) != 0) { 
       punchCursor.moveToLast(); 
       Calendar lastIn = Calendar.getInstance(); 
       lastIn.setTimeInMillis(punchCursor.getLong(0)); 

       updateClock((TextView)findViewById(R.id.in_punch_time_textview), lastIn); 

       inPunchLabel.setVisibility(View.VISIBLE); 
       inPunchLabel.setAnimation(fadeInAnimation); 
       inPunchLabel.startAnimation(fadeInAnimation); 

       inPunchTV.setVisibility(View.VISIBLE); 
       inPunchTV.setAnimation(fadeInAnimation); 
       inPunchTV.startAnimation(fadeInAnimation); 
      } 
      else { 
       //only fade when "turning off" last punch display 
       // (don't fade away when returning to screen) 
       if (inPunchLabel.getVisibility() == View.VISIBLE) { 
        inPunchLabel.setAnimation(fadeOutAnimation); 
        inPunchLabel.startAnimation(fadeOutAnimation); 
        inPunchLabel.setVisibility(View.INVISIBLE); 

        inPunchTV.setAnimation(fadeOutAnimation); 
        inPunchTV.startAnimation(fadeOutAnimation); 
        inPunchTV.setVisibility(View.INVISIBLE); 
       } 
      } 
      punchCursor.close(); 
     } //end getLastInPunch() 
    } //end TimepunchActivity 

奇怪的但是,這個錯誤並不是持久的。

我必須做更多,然後調用.close()嗎?

+0

「用printf調試」。您可以在每個打開和關閉(以及其他操作)之前使用一些日誌語句來查看發生了什麼。 – 2010-08-25 01:29:55

回答

4

問題是你在onCreate和onResume中創建/打開它,所以你要做兩次。同樣,你會關閉它兩次,所以它可能會崩潰。一般 - 你爲什麼不使用SQLiteOpenHelper?這將使管理你的數據庫變得更容易。

+0

謝謝。我以爲我正在重新初始化onResume中的對象。那麼我應該在重新初始化之前明確地關閉它嗎?當我開始看到這個錯誤時,我只有onPause;我甚至沒有onStop或onDestroy,直到我感到沮喪並添加它們。 我沒有使用SQLiteOpenHelper,因爲我認爲這是因爲我的數據庫需求是如此基本(基本上它是一個簡單的數組;一列長)我可以在活動中做它,而不是創建另一個類。這是錯誤的推理嗎? – hermy 2010-08-25 03:33:43

+1

我再次建議SQLiteOpenHelper大量減少工作量。一般來說,我只會在onResume中處理數據庫,然後在onPause中關閉它。如果你必須在onCreate中使用數據庫,那麼在onDestroy中執行它並關閉它 - 始終是對稱的。請參閱發送的鏈接CDonner。如果你到了onResume,你保證已經通過onCreate。 – EboMike 2010-08-25 04:16:55

+0

我的設計很糟糕 - 在onCreate和onResume中打開。我放棄了onPause和onStop方法,只保留了onDestroy,並且只在onCreate中創建/打開數據庫。似乎現在工作正常。但是,我會回顧並按照您的建議檢查SQLiteOpenHelper。謝謝您的幫助。 – hermy 2010-08-25 17:08:41

2

爲了支持EboMike的觀點,請看Android Activity lifecycle,你的代碼問題會很明顯。

+0

謝謝您將我指向參考頁面。儘管我已經閱讀過很多次(儘管不完整),但我知道這些事情。我的設計很糟糕 - 在onCreate和onResume中打開。我放棄了onPause和onStop方法,只保留了onDestroy,並且只在onCreate中創建/打開數據庫。似乎現在工作正常。謝謝。 – hermy 2010-08-25 17:07:06

相關問題