将正确的应用程序上下文传递给数据库处理程序失败

问题描述

我正在开发一个带有数据库的 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() 方法