调用getReadableDatabase()时出现空指针异常

时间:2013-07-20 20:33:16

标签: android android-sqlite

我对整个SQLite android实现相当新,我对如何摆脱这个错误无能为力。基本上我正在尝试用我的数据库保存用户数据(9个数组列表,每个数组最多包含20个元素)。我有一个应用程序,用户可以在地图上绘制点并进行“公路旅行”。然后他们可以选择保存那次公路旅行。我将每次公路旅行保存为一张桌子并抓住所需的信息。

这是我的代码。我试图调用方法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 个答案:

答案 0 :(得分:2)

摆脱close()上呼叫的大部分SQLiteDatabase方法。值得注意的是,不要在close()的{​​{1}}中传递给您的数据库上调用onCreate(),并且不要继续打开和关闭数据库。

SQLiteOpenHelper保留使用SQLiteOpenHelper / getReadableDatabase()检索到的数据库,重点是您可以重复使用已打开的getWritableDatabase()对象,尤其是当您在多线程。