调用getReadableDatabase时的空指针异常() [英] Null Pointer Exception when calling getReadableDatabase()
问题描述
我相当新的全SQLite的Android的实施,我就如何做才能摆脱这种错误的无能。从本质上讲什么,我想用我的数据库做的是保存用户数据(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屋!