调用getReadableDatabase时的空指针异常() [英] Null Pointer Exception when calling getReadableDatabase()

查看:1370
本文介绍了调用getReadableDatabase时的空指针异常()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我相当新的全SQLite的Andr​​oid的实施,我就如何做才能摆脱这种错误的无能。从本质上讲什么,我想用我的数据库做的是保存用户数据(9数组列表,最多每个人20元的)。我有一个应用程序,用户可以在地图上绘制点,做一个道之旅。然后,他们有选择地保存的客场之旅。我保存每个客场之旅作为一个表,并抢得所需的信息。

下面是我的code。我想调用的方法公开的ArrayList<串GT; getTableNames()来填充微调,它失败在该方法中的第一行。

 包com.example.roadtripplanner;进口的java.util.ArrayList;进口com.google.android.gms.maps.model.LatLng;进口android.content.ContentValues​​;
进口android.content.Context;
进口android.database.Cursor;
进口android.database.sqlite.SQLiteDatabase;
进口android.database.sqlite.SQLiteOpenHelper;公共类数据库处理器扩展SQLiteOpenHelper {    //数据库版本
    私有静态最终诠释DATABASE_VERSION = 2;    //数据库名称
    私有静态最后弦乐DATABASE_NAME =rtpDatabase;    公共数据库处理器(上下文的背景下){
        超(背景下,DATABASE_NAME,空,DATABASE_VERSION);
    }    //字符串创建的第一个表。
    公共静态最后弦乐TABLE_COMMENTS =意见;
    公共静态最后弦乐COLUMN_ID =_id;
    公共静态最后弦乐COLUMN_COMMENT =评论;
    私有静态最后弦乐DATABASE_CREATE =CREATE TABLE
        + TABLE_COMMENTS +(+ COLUMN_ID
        +整数主键自动增量+ COLUMN_COMMENT
        +文字NOT NULL);;
    @覆盖
    公共无效的onCreate(SQLiteDatabase DB){
        db.execSQL(DATABASE_CREATE);
        db.close();
    }    @覆盖
    公共无效onUpgrade(SQLiteDatabase分贝,INT oldVersion,诠释静态网页){
        db.execSQL(DROP TABLE IF EXISTS+ TABLE_COMMENTS);
        的onCreate(DB);
    }    公共无效addTable(字符串说明书){
        SQLiteDatabase分贝= this.getWritableDatabase();
        db.execSQL(说明书);
        db.close();    }    公共无效addTableValues​​(字符串tableName值,ArrayList的<&经纬度GT; latLngList,ArrayList的<串GT; stringList1,ArrayList的<串GT; stringList2){
        SQLiteDatabase分贝= this.getWritableDatabase();        ContentValues​​值=新ContentValues​​();
        values​​.put(的latLng,latLngList.get(0).latitude + latLngList.get(0).longitude);
        values​​.put(字符串1,stringList1.get(0));
        values​​.put(字符串2,stringList2.get(0));        //插入行
        db.insert(tableName值,空,价值);
        db.close(); //关闭数据库连接
    }    公共字符串getTableValues​​(字符串tableName值){
        SQLiteDatabase分贝= this.getReadableDatabase();
        光标CUR = db.query(tableName值,新的String [] {的latLng,字符串1
            字符串2},NULL,NULL,NULL,NULL,NULL);
        串富=;
        cur.moveToFirst(); //你的光标移动到第一行
        //循环通过游标
        而(cur.isAfterLast()== FALSE){
            富=0:+ cur.getString(0)+1:+ cur.getString(1)+2:+ cur.getString(2);
            的System.out.println(0:+ cur.getString(0)); //给你拿数据
            的System.out.println(1:+ cur.getString(1));
            的System.out.println(2:+ cur.getString(2));
            cur.moveToNext();
        }        cur.close();
        返回foo的;
    }    公众的ArrayList<串GT; getTableNames(){
        SQLiteDatabase分贝= this.getReadableDatabase();
        ArrayList的<串GT;表名=新的ArrayList<串GT;();
        光标C = db.rawQuery(选择的名字从SQLITE_MASTER其中type ='表',NULL);
        如果(c.moveToFirst())
        {
            c.moveToNext(); //跳过第一个结果是不是表名。
            而(!c.isAfterLast()){
                tableNames.add(c.getString(c.getColumnIndex(名称)))​​;
               c.moveToNext();
            }
        }
        c.close();
        返回的表名;
    }    公共无效dropTables(){
        SQLiteDatabase分贝= this.getWritableDatabase();        的for(int i = 0; I< getTableNames()大小();我++){
            db.execSQL(DROP TABLE IF EXISTS'+ getTableNames()获得(I)+。');
            db.close();
        }
    }    //检查,看是否表已经存在
    布尔doesTableExist(字符串tableName值)
    {
        SQLiteDatabase分贝= this.getWritableDatabase();
        如果(tableName值== NULL ||分贝== NULL ||!db.isOpen())
        {
            返回false;
        }
        光标光标= db.rawQuery(FROM SQLITE_MASTER SELECT COUNT(*)其中type = AND名字=?,新的String [] {表中,TableName});
        如果(!cursor.moveToFirst())
        {
            返回false;
        }
        诠释计数= cursor.getInt(0);
        cursor.close();
        返回计数> 0;
    }}

和我打电话公开的ArrayList<串GT; getTableNames()这里另一个类...

 数据库处理器DB =新的数据库处理器(本);@覆盖
公共无效的onCreate(捆绑savedInstanceState){
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.startpage);
    mContext =这一点;    如果(db.getTableNames()。大小()== 0){
        trips_options.add(没有公路旅行保存);
    }其他{
        的for(int i = 0; I< db.getTableNames()大小();我++){
            。字符串TEMP = db.getTableNames()获得(I)
            //删除下划线暂时使标题查找用户更好的。
            //它们时将用户选择的跳闸被放回。
            TEMP = temp.replaceAll(_,);
            trips_options.add(db.getTableNames()获得(一));
        }
    }    tripsAdapter =新ArrayAdapter<串GT;(StartPageActivity.this,android.R.layout.simple_spinner_item,trips_options);
    tripsSpinner =(微调)findViewById(R.id.spinner_trips);
    tripsSpinner.setAdapter(tripsAdapter);
    addListenerOnButton();
}

LogCat中....

  07-20 16:28:33.693:E / AndroidRuntime(11397):致命异常:主要
07-20 16:28:33.693:E / AndroidRuntime(11397):了java.lang.RuntimeException:无法启动活动ComponentInfo {com.example.roadtripplanner / com.example.roadtripplanner.StartPageActivity}:java.lang.IllegalStateException:尝试重新打开已关闭的对象:SQLiteDatabase:/data/data/com.example.roadtripplanner/databases/rtpDatabase
07-20 16:28:33.693:E / AndroidRuntime(11397):在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2100)
07-20 16:28:33.693:E / AndroidRuntime(11397):在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2132)
07-20 16:28:33.693:E / AndroidRuntime(11397):在android.app.ActivityThread.access $ 600(ActivityThread.java:139)
07-20 16:28:33.693:E / AndroidRuntime(11397):在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1231)
07-20 16:28:33.693:E / AndroidRuntime(11397):在android.os.Handler.dispatchMessage(Handler.java:99)
07-20 16:28:33.693:E / AndroidRuntime(11397):在android.os.Looper.loop(Looper.java:137)
07-20 16:28:33.693:E / AndroidRuntime(11397):在android.app.ActivityThread.main(ActivityThread.java:5021)
07-20 16:28:33.693:E / AndroidRuntime(11397):在java.lang.reflect.Method.invokeNative(本机方法)
07-20 16:28:33.693:E / AndroidRuntime(11397):在java.lang.reflect.Method.invoke(Method.java:511)
07-20 16:28:33.693:E / AndroidRuntime(11397):在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:789)
07-20 16:28:33.693:E / AndroidRuntime(11397):在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
07-20 16:28:33.693:E / AndroidRuntime(11397):在dalvik.system.NativeStart.main(本机方法)
07-20 16:28:33.693:E / AndroidRuntime(11397):java.lang.IllegalStateException:产生的原因试图重新打开一个已关闭的对象:SQLiteDatabase:/data/data/com.example.roadtripplanner/databases / rtpDatabase
07-20 16:28:33.693:E / AndroidRuntime(11397):在android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
07-20 16:28:33.693:E / AndroidRuntime(11397):在android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:520)
07-20 16:28:33.693:E / AndroidRuntime(11397):在android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:263)
07-20 16:28:33.693:E / AndroidRuntime(11397):在android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:188)
07-20 16:28:33.693:E / AndroidRuntime(11397):在com.example.roadtripplanner.DatabaseHandler.getTableNames(DatabaseHandler.java:85)
07-20 16:28:33.693:E / AndroidRuntime(11397):在com.example.roadtripplanner.StartPageActivity.onCreate(StartPageActivity.java:52)
07-20 16:28:33.693:E / AndroidRuntime(11397):在android.app.Activity.performCreate(Activity.java:5058)
07-20 16:28:33.693:E / AndroidRuntime(11397):在android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
07-20 16:28:33.693:E / AndroidRuntime(11397):在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2064)
07-20 16:28:33.693:E / AndroidRuntime(11397):... 11个


解决方案

摆脱大部分的的close()方法,您正在呼吁 SQLiteDatabase 。值得注意的是,不叫的close()传递给你的数据库的onCreate(上) SQLiteOpenHelper ,不保持打开和关闭数据库。

SQLiteOpenHelper 保存到您检索与数据库getReadableDatabase() / getWritableDatabase() ,并且这个点为你重用打开 SQLiteDatabase 的对象,尤其是当你在多线程工作。

I fairly new to the whole SQLite android implementation and I am clueless on what to do to get rid of this error. Essentially what I am trying to do with my database is save user data (9 Array lists with a maximum of 20 elements in each of them). I have an app where users can plot points on a map and make a "Road Trip". They then have a choice to save that road trip. I am saving each road trip as a table and grabbing the information needed.

Here is my code. I am trying to call the method public ArrayList<String> getTableNames() to populate a spinner and it is failing on the first line in that method.

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;
    }

}

And I'm calling public ArrayList<String> getTableNames() in another class here...

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

解决方案

Get rid of most of your close() methods that you are calling on SQLiteDatabase. Notably, do not call close() on the database passed to you in onCreate() of SQLiteOpenHelper, and do not keep opening and closing the database.

SQLiteOpenHelper holds onto the database you retrieve with getReadableDatabase()/getWritableDatabase(), and the point is for you to reuse that opened SQLiteDatabase object, particularly as you do work across multiple threads.

这篇关于调用getReadableDatabase时的空指针异常()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆