2013-07-20 3 views
0

나는 전체 SQLite android 구현에 새로운 것이므로이 오류를 없애기 위해 무엇을 해야할지에 대해 간절히 바란다. 본질적으로 내 데이터베이스로 할 일은 사용자 데이터를 저장하는 것입니다 (각각에 최대 20 개의 요소가있는 9 개의 배열 목록). 나는 사용자가지도상의 포인트를 그릴 수 있고 "로드 트립"을 할 수있는 앱을 가지고있다. 그런 다음 여행을 저장하는 선택권이 있습니다. 나는 각 도로 여행을 테이블로 저장하고 필요한 정보를 얻고있다.getReadableDatabase()를 호출 할 때의 Null 포인터 예외

여기 내 코드입니다. 회 전자를 채우기 위해 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(); 
} 

로그 캣 ....

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();"를 모두 제거하십시오. 수동으로 db를 닫지 마십시오 – JafarKhQ

답변

2

은 당신이 당신의 close() 방법의 대부분을 제거하십시오 SQLiteDatabase으로 전화하십시오. 특히 onCreate()SQLiteOpenHelper으로 전달 된 데이터베이스에서 close()을 호출하지 말고 데이터베이스를 열어 두거나 닫지 마십시오.

SQLiteOpenHelpergetReadableDatabase()/getWritableDatabase()으로 검색 데이터베이스에 보유하고, 당신이 당신이 여러 스레드에서 작동 할 특히로서, SQLiteDatabase 개체를 열 재사용하는 점입니다.

+1

언제 데이터베이스를 닫아야합니까? 못? – Zack

+0

@Zack : 데이터베이스에 대한 작업이 완전히 끝났다고 확신할만한 것이 분명하다면 거기에서 닫으십시오. 그렇지 않으면 "절대"가능성이 높습니다. 예를 들어, 만일 당신이 당신의 데이터베이스를'ContentProvider'로 포장한다면,'ContentProvider'는 절대로 파괴되지 않으므로 결코 데이터베이스를 닫을 기회가 없습니다. SQLite는 트랜잭션 처리가 가능합니다. 데이터베이스를 닫지 못하면 일부 버퍼가 플러시되지 못하는 것은 아닙니다. – CommonsWare

+0

그럼 여기 시나리오가 있습니다. 내 응용 프로그램은 사용자가 3 페이지의 선택을 거칠 수있게하며, 3 페이지 후에는 선택에 따라 결과가있는 최종 페이지로 전송됩니다. 사용자는 앱을 다시 열 때 선택 항목이있는 "테이블"을로드 할 수 있도록 선택 항목을 저장할 수 있습니다. 그렇게함으로써 처음 세 페이지를 건너 뛸 수 있습니다. 그 시나리오를 보면, 내가 그것을 닫아야 할 필요가 있습니까? – Zack