2013-07-20 74 views
0

對於整個SQLite android實現我相當陌生,而且我對於如何擺脫此錯誤毫無頭緒。從本質上講,我試圖用我的數據庫來保存用戶數據(每個數組中最多有20個元素的9個數組列表)。我有一個應用程序,用戶可以在地圖上繪製點並進行「道路旅行」。然後他們可以選擇保存該路程。我將每次公路旅行都保存爲一張桌子,並抓取所需的信息。調用getReadableDatabase()時出現空指針異常

這是我的代碼。我試圖調用方法public ArrayList<String> getTableNames()來填充微調器,並且在該方法的第一行中失敗。

package com.example.roadtripplanner; 

import java.util.ArrayList; 

import com.google.android.gms.maps.model.LatLng; 

import android.content.ContentValues; 
import android.content.Context; 
import android.database.Cursor; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteOpenHelper; 

public class DatabaseHandler extends SQLiteOpenHelper { 

    // Database Version 
    private static final int DATABASE_VERSION = 2; 

    // Database Name 
    private static final String DATABASE_NAME = "rtpDatabase"; 

    public DatabaseHandler(Context context) { 
     super(context, DATABASE_NAME, null, DATABASE_VERSION); 
    } 

    //Strings to create the first table. 
    public static final String TABLE_COMMENTS = "comments"; 
    public static final String COLUMN_ID = "_id"; 
    public static final String COLUMN_COMMENT = "comment"; 
    private static final String DATABASE_CREATE = "create table " 
     + TABLE_COMMENTS + "(" + COLUMN_ID 
     + " integer primary key autoincrement, " + COLUMN_COMMENT 
     + " text not null);"; 
    @Override 
    public void onCreate(SQLiteDatabase db) { 
     db.execSQL(DATABASE_CREATE); 
     db.close(); 
    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     db.execSQL("DROP TABLE IF EXISTS " + TABLE_COMMENTS); 
     onCreate(db); 
    } 

    public void addTable(String statment) { 
     SQLiteDatabase db = this.getWritableDatabase(); 
     db.execSQL(statment); 
     db.close(); 

    } 

    public void addTableValues(String tableName, ArrayList<LatLng> latLngList,   ArrayList<String> stringList1, ArrayList<String> stringList2){ 
     SQLiteDatabase db = this.getWritableDatabase(); 

     ContentValues values = new ContentValues(); 
     values.put("latLng", latLngList.get(0).latitude + latLngList.get(0).longitude); 
     values.put("string1", stringList1.get(0)); 
     values.put("string2", stringList2.get(0)); 

     // Inserting Rows 
     db.insert(tableName, null, values); 
     db.close(); // Closing database connection 
    } 

    public String getTableValues(String tableName){ 
     SQLiteDatabase db = this.getReadableDatabase(); 
     Cursor cur = db.query(tableName, new String[] {"latLng", "string1", 
      "string2"}, null, null, null, null, null); 
     String foo = ""; 
     cur.moveToFirst(); // move your cursor to first row 
     // Loop through the cursor 
     while (cur.isAfterLast() == false) { 
      foo = "0: " + cur.getString(0) + "1: " + cur.getString(1) + "2: " + cur.getString(2); 
      System.out.println("0: " + cur.getString(0)); // will fetch you the data 
      System.out.println("1: " + cur.getString(1)); 
      System.out.println("2: " + cur.getString(2)); 
      cur.moveToNext(); 
     } 

     cur.close(); 
     return foo; 
    } 

    public ArrayList<String> getTableNames(){ 
     SQLiteDatabase db = this.getReadableDatabase(); 
     ArrayList<String> tableNames = new ArrayList<String>(); 
     Cursor c = db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null); 
     if (c.moveToFirst()) 
     { 
      c.moveToNext(); //Skipping first result which is not a table name. 
      while (!c.isAfterLast()){ 
       tableNames.add(c.getString(c.getColumnIndex("name"))); 
       c.moveToNext(); 
      } 
     } 
     c.close(); 
     return tableNames; 
    } 

    public void dropTables(){ 
     SQLiteDatabase db = this.getWritableDatabase(); 

     for(int i=0; i < getTableNames().size(); i++){ 
      db.execSQL("DROP TABLE IF EXISTS '" + getTableNames().get(i) + "'"); 
      db.close(); 
     } 
    } 

    //Checks to see if a table already exists 
    boolean doesTableExist(String tableName) 
    { 
     SQLiteDatabase db = this.getWritableDatabase(); 
     if (tableName == null || db == null || !db.isOpen()) 
     { 
      return false; 
     } 
     Cursor cursor = db.rawQuery("SELECT COUNT(*) FROM sqlite_master WHERE type = ? AND name = ?", new String[] {"table", tableName}); 
     if (!cursor.moveToFirst()) 
     { 
      return false; 
     } 
     int count = cursor.getInt(0); 
     cursor.close(); 
     return count > 0; 
    } 

} 

我打電話來這裏另一個類public ArrayList<String> getTableNames() ...

DatabaseHandler db = new DatabaseHandler(this); 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.startpage); 
    mContext = this; 

    if(db.getTableNames().size() == 0){ 
     trips_options.add("No Road Trips Saved"); 
    } else { 
     for(int i=0; i < db.getTableNames().size(); i++){ 
      String temp = db.getTableNames().get(i); 
      //Removing underscores for the time being to make the titles look better for the user. 
      //They will be put back when a user selected a trip. 
      temp = temp.replaceAll("_", " "); 
      trips_options.add(db.getTableNames().get(i)); 
     } 
    } 

    tripsAdapter = new ArrayAdapter<String>(StartPageActivity.this, android.R.layout.simple_spinner_item,trips_options); 
    tripsSpinner = (Spinner)findViewById(R.id.spinner_trips); 
    tripsSpinner.setAdapter(tripsAdapter); 
    addListenerOnButton(); 
} 

logcat的....

07-20 16:28:33.693: E/AndroidRuntime(11397): FATAL EXCEPTION: main 
07-20 16:28:33.693: E/AndroidRuntime(11397): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.roadtripplanner/com.example.roadtripplanner.StartPageActivity}: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/com.example.roadtripplanner/databases/rtpDatabase 
07-20 16:28:33.693: E/AndroidRuntime(11397): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2100) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2132) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at android.app.ActivityThread.access$600(ActivityThread.java:139) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1231) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at android.os.Handler.dispatchMessage(Handler.java:99) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at android.os.Looper.loop(Looper.java:137) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at android.app.ActivityThread.main(ActivityThread.java:5021) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at java.lang.reflect.Method.invokeNative(Native Method) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at java.lang.reflect.Method.invoke(Method.java:511) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at dalvik.system.NativeStart.main(Native Method) 
07-20 16:28:33.693: E/AndroidRuntime(11397): Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/com.example.roadtripplanner/databases/rtpDatabase 
07-20 16:28:33.693: E/AndroidRuntime(11397): at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:520) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:263) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:188) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at com.example.roadtripplanner.DatabaseHandler.getTableNames(DatabaseHandler.java:85) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at com.example.roadtripplanner.StartPageActivity.onCreate(StartPageActivity.java:52) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at android.app.Activity.performCreate(Activity.java:5058) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079) 
07-20 16:28:33.693: E/AndroidRuntime(11397): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2064) 
07-20 16:28:33.693: E/AndroidRuntime(11397): ... 11 more 
+1

刪除所有「db.close();」,從不關閉數據庫手動 – JafarKhQ

回答

2

擺脫你的大部分close()方法,你是呼籲SQLiteDatabase。值得注意的是,不要在SQLiteOpenHelperonCreate()傳遞給你的數據庫上調用close(),並且不要打開和關閉數據庫。

SQLiteOpenHelper持有到你getReadableDatabase()/getWritableDatabase()檢索數據庫,關鍵是你要重用打開SQLiteDatabase對象,尤其是你在多個線程運行。

+1

何時應該關閉我的數據庫呢?決不? – Zack

+0

@Zack:如果您確定完全用數據庫完成了某個清點,請將其關閉。否則,「從不」是一個可能的答案。例如,如果要將數據庫包裝到「ContentProvider」中,則「ContentProvider」永遠不會被銷燬,因此永遠不會有機會關閉其數據庫。 SQLite是事務性的;未能關閉數據庫並不意味着某些緩衝區無法刷新(或其他)。 – CommonsWare

+0

那麼這是一個場景。我的應用程序允許用戶瀏覽3頁的選擇內容,並在這三頁之後將它們發送到基於他們的選擇結果的最終頁面。用戶可以選擇保存選擇,以便當他們再次打開應用程序時,他們可以加載其中包含所有選擇的「表格」。通過這樣做,他們可以跳過前三頁。看看這種情況,我是否需要關閉它? – Zack