如何修复我的 Android SQLite 数据库?
How can I fix my Android SQLite Database?
我是开发 android 应用程序的初级程序员,所以我真的需要您的帮助。
我知道我的问题很长,但如果你们能回答我的问题,我将不胜感激
我正在制作一个应用程序,它从 table 中的多个单词中 运行domly 选择 1 个单词。
因此,我用 SQLite 创建了我的数据库。我试过这些东西。
- 我让 WordDBHelper 使用 SQLiteOpenHelper
- 我制作了 WordDBRecord 以将记录放入 table
- 我制作了 WordActivty 以打开数据库并查看从 table 到 TextView.setText() 中选择的单词。
这些是我的代码
- 单词Activity
public class WordActivity extends AppCompatActivity {
private WordDBRecord wordDBRecord;
String category = wordDBRecord.category;
String word = wordDBRecord.word;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_word);
TextView t1 = (TextView) findViewById(R.id.textViewCategory);
TextView t2 = (TextView) findViewById(R.id.textViewWord);
wordDBRecord = new WordDBRecord(this);
wordDBRecord.open();
wordDBRecord.DBSearch("KeyWordDB");
t1.setText(category);
t2.setText(word);
wordDBRecord.close();
}
}
- WordDBHelper(使用 SQLite Open Helper)
import static android.content.ContentValues.TAG;
public class WordDBHelper extends SQLiteOpenHelper {
static final String TABLE_NAME = "KeyWordDB";
public WordDBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
Log.d(TAG, "DataBaseHelper");
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
Log.d(TAG, "Table Create");
String createQuery = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME +
"( ID INTEGER PRIMARY KEY AUTOINCREMENT, " +
"CATEGORY TEXT NOT NULL, " +
"WORD TEXT NOT NULL);";
sqLiteDatabase.execSQL(createQuery);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
Log.d(TAG, "Table onUpgrade");
String createQuery = "DROP TABLE IF EXISTS " + TABLE_NAME + ";";
sqLiteDatabase.execSQL(createQuery);
}
}
3.WordDBRecord(Class放记录)
import static android.content.ContentValues.TAG;
public class WordDBRecord {
public String id;
public String category;
public String word;
private Context context;
private WordDBHelper dbHelper;
private SQLiteDatabase database;
public WordDBRecord(Context c) {
context = c;
}
public WordDBRecord open() throws SQLException {
dbHelper = new WordDBHelper(context, "DB", null, 1);
database = dbHelper.getWritableDatabase();
dbInsert("KeyWordDB", "Movie", "Harry Potter");
return this;
}
public void DBSearch(String tableName) {
Cursor cursor = null;
try {
cursor = database.query(tableName, null, null, null, null, null, null);
if (cursor != null) {
while (cursor.moveToNext()) {
id = cursor.getString(cursor.getColumnIndex("ID"));
category = cursor.getString(cursor.getColumnIndex("CATEGORY"));
word = cursor.getString(cursor.getColumnIndex("WORD"));
}
}
} finally {
if (cursor != null) {
cursor.close();
}
}
}
public void close() {
database.close();
dbHelper.close();
}
public void dbInsert(String tableName, String category, String word) {
Log.d(TAG, "Insert Data ");
ContentValues contentValues = new ContentValues();
contentValues.put("CATEGORY", category);
contentValues.put("WORD", word);
long id = database.insert(tableName, null, contentValues);
Log.d(TAG, "id: " + id);
}
}
所以我 运行 我的应用程序,但我无法打开应用程序。单击我的应用程序时,我的应用程序停止了。
我收到了那些 Logcats
2019-12-15 11:37:59.005 22791-22791/org.techtown.worddbpractice E/AndroidRuntime: FATAL EXCEPTION: main
Process: org.techtown.worddbpractice, PID: 22791
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{org.techtown.worddbpractice/org.techtown.worddbpractice.WordActivity}: java.lang.NullPointerException: Attempt to read from field 'java.lang.String org.techtown.worddbpractice.WordDBRecord.category' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2849)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3045)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1642)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
Caused by: java.lang.NullPointerException: Attempt to read from field 'java.lang.String org.techtown.worddbpractice.WordDBRecord.category' on a null object reference
at org.techtown.worddbpractice.WordActivity.<init>(WordActivity.java:17)
at java.lang.Class.newInstance(Native Method)
at android.app.Instrumentation.newActivity(Instrumentation.java:1086)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2839)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3045)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1642)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
我真的很想解决这些问题,但我不知道如何...
如果有人回答我的超长问题,我将非常感激。
谢谢
请在 DBSearch() 方法中尝试此查询。
public void DBSearch(String tableName) {
Cursor cursor = null;
try {
Cursor cursor = db.rawQuery("SELECT name FROM "+tablename, null);
if (cursor != null) {
while (cursor.moveToNext()) {
id = cursor.getString(cursor.getColumnIndex("ID"));
category = cursor.getString(cursor.getColumnIndex("CATEGORY"));
word = cursor.getString(cursor.getColumnIndex("WORD"));
}
}
} finally {
if (cursor != null) {
cursor.close();
}
}
}
说明
您面临的问题是,当您使用 private WordDBRecord wordDBRecord;
时,这会将变量 wordDBRecord 声明为 WordDBRecord 类型,它不是 primative 类型,而是 Object.
声明 一个不是原始类型的变量会导致该变量为 null(即没有 object 存在(尚未创建 object)。
所以当遇到下一行String category = wordDBRecord.category;
时有没有object wordDBRecord而不是指向 object 的指针设置为 null 以表明这一点。因此,当尝试从 object 中获取类别时,您会得到 空指针异常 (您无法从无到有)。
如果遇到下一行 String word = wordDBRecord.word;
,也会出现同样的问题。
如何修复(空指针异常)
修复很简单,在实例化 wordDBRecord 之前,不要尝试使用 wordDBRecord 来设置类别和词的值。实例化由 wordDBRecord = new WordDBRecord(this);
.
行完成
因此您只想声明 category 和 word 变量。例如
public class WordActivity extends AppCompatActivity {
private WordDBRecord wordDBRecord; //<<<<< only declares wordDBrecord so it is null
String category; //<<<<< CHANGED TO ONLY DECLARE category
String word; //<<<<< CHANGED TO ONLY DECALRE word
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView t1 = (TextView) findViewById(R.id.textViewCategory);
TextView t2 = (TextView) findViewById(R.id.textViewWord);
wordDBRecord = new WordDBRecord(this); //<<<<< instantiates wordDBRecord so it is now not null
wordDBRecord.open();
wordDBRecord.DBSearch("KeyWordDB");
t1.setText(category);
t2.setText(word);
wordDBRecord.close();
}
}
然而 - 完成修复
应用修复后,您将不会在 TextView 中看到电影和哈利波特。
这是因为上面的代码运行时声明了类别和词,但它们从未被设置(它们为空,但 setText 方法对此进行检查并绕过空指针异常) .您需要设置值,例如在行 wordDBRecord.DBSearch("KeyWordDB");
之后使用 :-
category = wordRecordDB.category;
word = wordRecordDB.word;
t1.setText(category);
t2.setText(word);
因为您可以直接从 wordDBRecord object 中获取值。甚至不需要具有可变类别和单词。因此,您可以使用更紧凑的 :-
public class WordActivity extends AppCompatActivity {
private WordDBRecord wordDBRecord; //<<<<< only declares wordDBrecord so it is null
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView t1 = (TextView) findViewById(R.id.textViewCategory);
TextView t2 = (TextView) findViewById(R.id.textViewWord);
wordDBRecord = new WordDBRecord(this); //<<<<< instantiates wordDBRecord so it is now not null
wordDBRecord.open();
wordDBRecord.DBSearch("KeyWordDB");
t1.setText(wordDBRecord.category);
t2.setText(wordDBRecord.word);
wordDBRecord.close();
}
}
使用以上结果:-
日志包含:-
2019-12-16 10:14:37.773 D/Constraints: DataBaseHelper
2019-12-16 10:14:37.789 D/Constraints: Table Create
2019-12-16 10:14:37.794 D/Constraints: Insert Data
2019-12-16 10:14:37.798 D/Constraints: id: 1
额外
在类似的主题上,SQliteDatabase 查询方法永远不会 return 为空的 Cursor。不需要在检索它之前将 Cursor 设置为 null 并在检索它之后检查它是否为 null。
因此,您的 DBSearch 方法可能是:-
public void DBSearch(String tableName) {
Cursor cursor = database.query(tableName,null,null,null,null,null,null);
while (cursor.moveToNext()) {
id = cursor.getString(cursor.getColumnIndex("ID"));
category = cursor.getString(cursor.getColumnIndex("CATEGORY"));
word = cursor.getString(cursor.getColumnIndex("WORD"));
}
cursor.close();
}
我是开发 android 应用程序的初级程序员,所以我真的需要您的帮助。 我知道我的问题很长,但如果你们能回答我的问题,我将不胜感激
我正在制作一个应用程序,它从 table 中的多个单词中 运行domly 选择 1 个单词。
因此,我用 SQLite 创建了我的数据库。我试过这些东西。
- 我让 WordDBHelper 使用 SQLiteOpenHelper
- 我制作了 WordDBRecord 以将记录放入 table
- 我制作了 WordActivty 以打开数据库并查看从 table 到 TextView.setText() 中选择的单词。
这些是我的代码
- 单词Activity
public class WordActivity extends AppCompatActivity {
private WordDBRecord wordDBRecord;
String category = wordDBRecord.category;
String word = wordDBRecord.word;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_word);
TextView t1 = (TextView) findViewById(R.id.textViewCategory);
TextView t2 = (TextView) findViewById(R.id.textViewWord);
wordDBRecord = new WordDBRecord(this);
wordDBRecord.open();
wordDBRecord.DBSearch("KeyWordDB");
t1.setText(category);
t2.setText(word);
wordDBRecord.close();
}
}
- WordDBHelper(使用 SQLite Open Helper)
import static android.content.ContentValues.TAG;
public class WordDBHelper extends SQLiteOpenHelper {
static final String TABLE_NAME = "KeyWordDB";
public WordDBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
Log.d(TAG, "DataBaseHelper");
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
Log.d(TAG, "Table Create");
String createQuery = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME +
"( ID INTEGER PRIMARY KEY AUTOINCREMENT, " +
"CATEGORY TEXT NOT NULL, " +
"WORD TEXT NOT NULL);";
sqLiteDatabase.execSQL(createQuery);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
Log.d(TAG, "Table onUpgrade");
String createQuery = "DROP TABLE IF EXISTS " + TABLE_NAME + ";";
sqLiteDatabase.execSQL(createQuery);
}
}
3.WordDBRecord(Class放记录)
import static android.content.ContentValues.TAG;
public class WordDBRecord {
public String id;
public String category;
public String word;
private Context context;
private WordDBHelper dbHelper;
private SQLiteDatabase database;
public WordDBRecord(Context c) {
context = c;
}
public WordDBRecord open() throws SQLException {
dbHelper = new WordDBHelper(context, "DB", null, 1);
database = dbHelper.getWritableDatabase();
dbInsert("KeyWordDB", "Movie", "Harry Potter");
return this;
}
public void DBSearch(String tableName) {
Cursor cursor = null;
try {
cursor = database.query(tableName, null, null, null, null, null, null);
if (cursor != null) {
while (cursor.moveToNext()) {
id = cursor.getString(cursor.getColumnIndex("ID"));
category = cursor.getString(cursor.getColumnIndex("CATEGORY"));
word = cursor.getString(cursor.getColumnIndex("WORD"));
}
}
} finally {
if (cursor != null) {
cursor.close();
}
}
}
public void close() {
database.close();
dbHelper.close();
}
public void dbInsert(String tableName, String category, String word) {
Log.d(TAG, "Insert Data ");
ContentValues contentValues = new ContentValues();
contentValues.put("CATEGORY", category);
contentValues.put("WORD", word);
long id = database.insert(tableName, null, contentValues);
Log.d(TAG, "id: " + id);
}
}
所以我 运行 我的应用程序,但我无法打开应用程序。单击我的应用程序时,我的应用程序停止了。 我收到了那些 Logcats
2019-12-15 11:37:59.005 22791-22791/org.techtown.worddbpractice E/AndroidRuntime: FATAL EXCEPTION: main
Process: org.techtown.worddbpractice, PID: 22791
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{org.techtown.worddbpractice/org.techtown.worddbpractice.WordActivity}: java.lang.NullPointerException: Attempt to read from field 'java.lang.String org.techtown.worddbpractice.WordDBRecord.category' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2849)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3045)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1642)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
Caused by: java.lang.NullPointerException: Attempt to read from field 'java.lang.String org.techtown.worddbpractice.WordDBRecord.category' on a null object reference
at org.techtown.worddbpractice.WordActivity.<init>(WordActivity.java:17)
at java.lang.Class.newInstance(Native Method)
at android.app.Instrumentation.newActivity(Instrumentation.java:1086)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2839)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3045)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1642)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
我真的很想解决这些问题,但我不知道如何... 如果有人回答我的超长问题,我将非常感激。 谢谢
请在 DBSearch() 方法中尝试此查询。
public void DBSearch(String tableName) {
Cursor cursor = null;
try {
Cursor cursor = db.rawQuery("SELECT name FROM "+tablename, null);
if (cursor != null) {
while (cursor.moveToNext()) {
id = cursor.getString(cursor.getColumnIndex("ID"));
category = cursor.getString(cursor.getColumnIndex("CATEGORY"));
word = cursor.getString(cursor.getColumnIndex("WORD"));
}
}
} finally {
if (cursor != null) {
cursor.close();
}
}
}
说明
您面临的问题是,当您使用 private WordDBRecord wordDBRecord;
时,这会将变量 wordDBRecord 声明为 WordDBRecord 类型,它不是 primative 类型,而是 Object.
声明 一个不是原始类型的变量会导致该变量为 null(即没有 object 存在(尚未创建 object)。
所以当遇到下一行String category = wordDBRecord.category;
时有没有object wordDBRecord而不是指向 object 的指针设置为 null 以表明这一点。因此,当尝试从 object 中获取类别时,您会得到 空指针异常 (您无法从无到有)。
如果遇到下一行 String word = wordDBRecord.word;
,也会出现同样的问题。
如何修复(空指针异常)
修复很简单,在实例化 wordDBRecord 之前,不要尝试使用 wordDBRecord 来设置类别和词的值。实例化由 wordDBRecord = new WordDBRecord(this);
.
因此您只想声明 category 和 word 变量。例如
public class WordActivity extends AppCompatActivity {
private WordDBRecord wordDBRecord; //<<<<< only declares wordDBrecord so it is null
String category; //<<<<< CHANGED TO ONLY DECLARE category
String word; //<<<<< CHANGED TO ONLY DECALRE word
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView t1 = (TextView) findViewById(R.id.textViewCategory);
TextView t2 = (TextView) findViewById(R.id.textViewWord);
wordDBRecord = new WordDBRecord(this); //<<<<< instantiates wordDBRecord so it is now not null
wordDBRecord.open();
wordDBRecord.DBSearch("KeyWordDB");
t1.setText(category);
t2.setText(word);
wordDBRecord.close();
}
}
然而 - 完成修复
应用修复后,您将不会在 TextView 中看到电影和哈利波特。
这是因为上面的代码运行时声明了类别和词,但它们从未被设置(它们为空,但 setText 方法对此进行检查并绕过空指针异常) .您需要设置值,例如在行 wordDBRecord.DBSearch("KeyWordDB");
之后使用 :-
category = wordRecordDB.category;
word = wordRecordDB.word;
t1.setText(category);
t2.setText(word);
因为您可以直接从 wordDBRecord object 中获取值。甚至不需要具有可变类别和单词。因此,您可以使用更紧凑的 :-
public class WordActivity extends AppCompatActivity {
private WordDBRecord wordDBRecord; //<<<<< only declares wordDBrecord so it is null
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView t1 = (TextView) findViewById(R.id.textViewCategory);
TextView t2 = (TextView) findViewById(R.id.textViewWord);
wordDBRecord = new WordDBRecord(this); //<<<<< instantiates wordDBRecord so it is now not null
wordDBRecord.open();
wordDBRecord.DBSearch("KeyWordDB");
t1.setText(wordDBRecord.category);
t2.setText(wordDBRecord.word);
wordDBRecord.close();
}
}
使用以上结果:-
日志包含:-
2019-12-16 10:14:37.773 D/Constraints: DataBaseHelper
2019-12-16 10:14:37.789 D/Constraints: Table Create
2019-12-16 10:14:37.794 D/Constraints: Insert Data
2019-12-16 10:14:37.798 D/Constraints: id: 1
额外
在类似的主题上,SQliteDatabase 查询方法永远不会 return 为空的 Cursor。不需要在检索它之前将 Cursor 设置为 null 并在检索它之后检查它是否为 null。
因此,您的 DBSearch 方法可能是:-
public void DBSearch(String tableName) {
Cursor cursor = database.query(tableName,null,null,null,null,null,null);
while (cursor.moveToNext()) {
id = cursor.getString(cursor.getColumnIndex("ID"));
category = cursor.getString(cursor.getColumnIndex("CATEGORY"));
word = cursor.getString(cursor.getColumnIndex("WORD"));
}
cursor.close();
}