问题描述
我正在开发一个带有数据库的 Android 应用程序,我在将正确的上下文传递给我的数据库处理程序时遇到了麻烦,因为我传递给数据库处理程序的应用程序上下文的实例似乎总是为空; 由于我已经为此工作了数小时以使其正常工作,我将不胜感激任何提示或建设性的反馈以完成这项工作。
应用程序总是以相同的空指针异常崩溃:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.Cursor android.database.sqlite.sqliteDatabase.rawQuery(java.lang.String,java.lang.String[])' on a null object reference
在方法DatabaseHandler.getAllItems中,这部分:
try (sqliteDatabase db = this.getWritableDatabase(GoldbekStorageApp.getInstance())) {
cursor = db.rawQuery(selectQuery,null);
}
这是我的数据库处理程序:
enter code here
包 com.example.xxx;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.sqliteDatabase;
import android.database.sqlite.sqliteOpenHelper;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class DatabaseHandler extends sqliteOpenHelper {
private static final int DATABASE_VERSION = 2;
private static final String DATABASE_NAME = "itemsManager";
private static final String TABLE_ITEMS = "items";
private static final String KEY_NO = "number";
private static final String TAG = "Database values";
private static final String KEY_NAME = "name";
private static final String KEY_EAN = "ean";
private static final String KEY_TYPE = "type";
private static final String KEY_ITEMGROUPNAME = "itemgroupname";
private static final String KEY_DESTRUCTION = "destruction";
private static final String KEY_ARCHIVED = "archived";
public static final String TAGGGG = "Datenbank" ;
private String No;
private String Ean;
private String Name;
private String Itemgroupname;
private String Type;
private Boolean Destruction;
private Boolean Archived;
public Context context;
public String uname;
public DatabaseHandler(Context context) {
super(context,DATABASE_NAME,null,DATABASE_VERSION);
//3rd argument to be passed is CursorFactory instance
this.context = context; // add this line to initialize your context.
}
// Creating Tables
@Override
public void onCreate(sqliteDatabase db) {
String CREATE_ITEMS_TABLE = "CREATE TABLE " + TABLE_ITEMS + "("
+ KEY_NO + " TEXT," + KEY_NAME + " TEXT,"
+ KEY_ITEMGROUPNAME + " TEXT,"
+ KEY_TYPE + " TEXT,"
+ KEY_EAN + " TEXT,"
+ KEY_DESTRUCTION + " BOOLEAN,"
+ KEY_ARCHIVED + " BOOLEAN" +")";
Log.d(TAG,CREATE_ITEMS_TABLE);
db.execsql(CREATE_ITEMS_TABLE);
}
public boolean getItemByEAN(String code) {
sqliteDatabase db = this.getWritableDatabase();
Cursor mCursor = db.rawQuery("SELECT * FROM items WHERE ean =?",new String[]{ Ean });
if (mCursor != null)
{
Log.d(TAGGGG,"Worked");
return true;
/* record exist */
}
else
{
Log.d(TAGGGG,"Did not worked");
return false;
/* record not exist */
}
}
public void checkItemAgainstDatabase(String code)
{
String selectQuery = "SELECT * FROM " + TABLE_ITEMS + " WHERE " + KEY_EAN + "='" + code + "'";
sqliteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery,null);
// looping through all rows and adding to list
if(cursor == null)
{
Log.d(TAGGGG,"Cursor ist Null,Item not present");
return;
}
if (cursor.getCount() == 0) {
Log.d(TAGGGG," Item not present");
} else {
Log.d(TAGGGG," Item present");
}
db.close();
return;
/*
for (Item item : itemList) {
String itemEanToBeMatched = item.getEan();
if (itemEanToBeMatched.equals(code)) {
Toast.makeText(Context,code,Toast.LENGTH_LONG).show();
//ScanService.checkEnteredCode(code,content,mContext.getApplicationContext());
}
String itemNoToBeMatched = item.getNo();
if (itemNoToBeMatched.equals(code)) {
Toast.makeText(mContext,mContext.getApplicationContext());
}
else {
Toast.makeText(mContext,R.string.not_in_database,Toast.LENGTH_LONG).show();
Vibrator vibrator;
vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(3000);
Uri notification = ringtoneManager.getDefaultUri(ringtoneManager.TYPE_NOTIFICATION);
ringtone r = ringtoneManager.getringtone(mContext.getApplicationContext(),notification);
r.play();
break;
}
} */
}
// Upgrading database
@Override
public void onUpgrade(sqliteDatabase db,int oldVersion,int newVersion) {
// Drop older table if existed
db.execsql("DROP TABLE IF EXISTS " + TABLE_ITEMS);
// Create tables again
onCreate(db);
}
// code to add the new item
public void addItem(Item items) {
sqliteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NO,""+items.getNo()); // Item Ean
values.put(KEY_EAN,""+items.getEan()); // Item Ean
values.put(KEY_NAME,items.getName()); // Item Name
values.put(KEY_TYPE,items.getType());
//values.put(KEY_ITEMGROUPNAM,item.getItemgroupname()); // Item Groupname
values.put(String.valueOf(KEY_ARCHIVED),items.getArchived());
values.put(String.valueOf(KEY_DESTRUCTION),items.getDestruction());
// Inserting Row
db.insert(TABLE_ITEMS,values);
//2nd argument is String containing nullColumnHack
db.close(); // Closing database connection
}
// code to get the single contact
public Item getItem(int id) {
sqliteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_ITEMS,new String[] { KEY_NO,KEY_NAME,KEY_EAN,KEY_TYPE,String.valueOf(KEY_ARCHIVED),String.valueOf(KEY_DESTRUCTION)},KEY_NO + "=?",new String[] { String.valueOf(id) },null);
if (cursor != null)
cursor.movetoFirst();
Item item = new Item(cursor.getString(0),cursor.getString(1),cursor.getString(2),cursor.getString(3),cursor.getString(4),cursor.getExtras().getBoolean(String.valueOf(5)),Boolean.getBoolean(String.valueOf(6)));
Log.d(TAGGGG,String.valueOf(item));
// return contact
return item;
}
// code to get all contacts in a list view
public List<Item> getAllItems(Context context) {
List<Item> itemList = new List<Item>() {
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean contains(@Nullable @org.jetbrains.annotations.Nullable Object o) {
return false;
}
@NonNull
@NotNull
@Override
public Iterator<Item> iterator() {
return null;
}
@NonNull
@NotNull
@Override
public Object[] toArray() {
return new Object[0];
}
@NonNull
@NotNull
@Override
public <T> T[] toArray(@NonNull @NotNull T[] a) {
return null;
}
@Override
public boolean add(Item item) {
return false;
}
@Override
public boolean remove(@Nullable @org.jetbrains.annotations.Nullable Object o) {
return false;
}
@Override
public boolean containsAll(@NonNull @NotNull Collection<?> c) {
return false;
}
@Override
public boolean addAll(@NonNull @NotNull Collection<? extends Item> c) {
return false;
}
@Override
public boolean addAll(int index,@NonNull @NotNull Collection<? extends Item> c) {
return false;
}
@Override
public boolean removeAll(@NonNull @NotNull Collection<?> c) {
return false;
}
@Override
public boolean retainAll(@NonNull @NotNull Collection<?> c) {
return false;
}
@Override
public void clear() {
}
@Override
public boolean equals(@Nullable @org.jetbrains.annotations.Nullable Object o) {
return false;
}
@Override
public int hashCode() {
return 0;
}
@Override
public Item get(int index) {
return null;
}
@Override
public Item set(int index,Item element) {
return null;
}
@Override
public void add(int index,Item element) {
}
@Override
public Item remove(int index) {
return null;
}
@Override
public int indexOf(@Nullable @org.jetbrains.annotations.Nullable Object o) {
return 0;
}
@Override
public int lastIndexOf(@Nullable @org.jetbrains.annotations.Nullable Object o) {
return 0;
}
@NonNull
@NotNull
@Override
public ListIterator<Item> listIterator() {
return null;
}
@NonNull
@NotNull
@Override
public ListIterator<Item> listIterator(int index) {
return null;
}
@NonNull
@NotNull
@Override
public List<Item> subList(int fromIndex,int toIndex) {
return null;
}
};
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_ITEMS;
Cursor cursor;
try (sqliteDatabase db = this.getWritableDatabase(GoldbekStorageApp.getInstance())) {
cursor = db.rawQuery(selectQuery,null);
}
// looping through all rows and adding to list
if (cursor.movetoFirst()) {
do {
Item item = new Item(No,Name,Itemgroupname,Ean,Type,Destruction,Archived);
item.setNo(cursor.getString(0));
item.setName(cursor.getString(1));
item.setEan(cursor.getString(2));
item.setType(cursor.getString(2));
// Adding items to list
itemList.add(item);
} while (cursor.movetoNext());
}
// return contact list
return itemList;
}
private sqliteDatabase getWritableDatabase(GoldbekStorageApp context) {
return null;
}
// code to update the single item
public int updateItem(Item item) {
sqliteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NO,item.getNo());
values.put(KEY_NAME,item.getName());
values.put(KEY_EAN,item.getEan());
values.put(KEY_ITEMGROUPNAME,item.getItemgroupname());
values.put(KEY_TYPE,item.getType());
values.put(String.valueOf(KEY_DESTRUCTION),item.getDestruction());
values.put(String.valueOf(KEY_ARCHIVED),item.getArchived());
// updating row
return db.update(TABLE_ITEMS,values,KEY_NO + " = ?",new String[] { String.valueOf(item.getNo()) });
}
// Deleting single item
public void deleteItem(Item item) {
sqliteDatabase db = this.getWritableDatabase();
db.delete(TABLE_ITEMS,new String[] { String.valueOf(item.getNo()) });
db.close();
}
// Getting items Count
public int getItemsCount() {
String itemQuery = "SELECT * FROM " + TABLE_ITEMS;
sqliteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(itemQuery,null);
cursor.close();
// return count
return cursor.getCount();
}
}
这是我在 MainActivity 中的 onCreate-Method,我在那里调用
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Sentry.captureMessage("testing SDK setup");
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getPosts();
//在以下几行中,我正在初始化我的应用程序的上下文并将其 // 传递给数据库处理程序和数据库中方法的方法调用 //Handler
*mContext = GoldbekStorageApp.getInstance();
DatabaseHandler db = new DatabaseHandler(mContext);
List<Item> items = db.getAllItems(mContext);*
new LongOperation().execute();
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(R.id.nav_palette,R.id.nav_home,R.id.nav_gallery,R.id.nav_slideshow)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this,R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this,navController,mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView,navController);
}
这是我定义应用程序上下文的方式:
import android.app.Application;
import android.content.Context;
public class GoldbekStorageApp extends Application {
private static Context mContext;
public static GoldbekStorageApp mInstance= null;
public String palNo;
public String getPalNo() {
return palNo;
}
public void setPalNo(String palNo) {
this.palNo = palNo;
}
public GoldbekStorageApp(){}
public static synchronized GoldbekStorageApp getInstance() {
if(null == mInstance){
mInstance = new GoldbekStorageApp();
}
return mInstance;
}
}
我有轻微的感觉,我未能初始化并将应用程序上下文传递给数据库处理程序,但我不知道我在哪里失败以及出了什么问题,因为我不是专家在Android中处理Context;因此,任何提示或帮助将不胜感激,谢谢!
解决方法
您需要将 GoldbekStorageApp 中的 getInstance 方法和 Ctor 更改为:
public static synchronized GoldbekStorageApp getInstance(Context con) {
if(null == mInstance){
mInstance = new GoldbekStorageApp(con);
}
return mInstance;
}
public GoldbekStorageApp(Context con){mContext = con}
请注意,我不知道为什么,我只知道我在几个地方读到过不推荐持有对应用程序上下文的静态引用。 第一次调用 getInstance 时,您需要确保传递有效的上下文(即 getApplicationContext() 或 MainActivity.this 或类似的东西)以后的调用可以通过传递 null 作为参数来进行,因为它无论如何都会被忽略
,这不是 Context
。
相反,您应该删除此方法:
private SQLiteDatabase getWritableDatabase(GoldbekStorageApp context) {
return null;
}
并且只使用 SQLiteOpenHelper#getWritableDatabase()
- 它不会返回空值,您可以在类的构造函数中将 Context
传递给它。
代码存在许多其他问题,这是 NPE 在尝试对 null 调用 rawQuery()
时的一个原因。
首先,不要创建 Application
对象。这是由 Android 完成的。
Static way to get 'Context' in Android?
第二,你真的需要它吗?活动有上下文。 它是 Context
,事实上。如果您需要应用程序上下文,则 Activity 具有 getApplicationContext()
方法