应用程序在 getWritableDatabase 崩溃:NullPointerException

App crashes at getWritableDatabase: NullPointerException

我正在尝试制作一个涉及数据库的应用程序。我正在使用 ContentProvider,当它尝试获取 WritableDatabase 时,它​​在查询方法中崩溃了。 它 returns 一个 NullPointerException。我知道 Context 不为空,因为这似乎是造成此类问题的主要原因。

这是 ContentProvider 代码:

package com.corvus.corvusenterprises.digimonapp;

import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

import java.util.Arrays;
import java.util.HashSet;

import static com.corvus.corvusenterprises.digimonapp.DBHelper.presentDigimon;

/**
 * Created by Jack on 01/05/2017.
 */

public class DigimonContentProvider extends ContentProvider {
    private static DigimonContentProvider instance;
    private DBHelper dbHelper;
    private SQLiteDatabase db;

    private static final int DIGIMON = 10;
    private static final int DIGIMON_ID = 20;
    private static final int ATTACKS = 30;
    private static final int ATTACKS_ID = 40;
    private static final int EVOLUTIONS = 50;
    private static final int EVOLUTIONS_ID = 60;

    private static final String AUTHORITY = "com.corvus.corvusenterprises.digimonapp";

    private static final String BASE_PATH_DIGIMON = "digimon";
    private static final String BASE_PATH_ATTACKS = "attacks";
    private static final String BASE_PATH_EVOLUTIONS = "evolutions";

    public static final Uri CONTENT_URI_DIGIMON = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH_DIGIMON);
    public static final Uri CONTENT_URI_ATTACKS = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH_ATTACKS);
    public static final Uri CONTENT_URI_EVOLUTIONS = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH_EVOLUTIONS);

    public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/digimon";
    public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/digimon";

    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    static {
        sURIMatcher.addURI(AUTHORITY, BASE_PATH_DIGIMON, DIGIMON);
        sURIMatcher.addURI(AUTHORITY, BASE_PATH_DIGIMON + "/#", DIGIMON_ID);
        sURIMatcher.addURI(AUTHORITY, BASE_PATH_ATTACKS, ATTACKS);
        sURIMatcher.addURI(AUTHORITY, BASE_PATH_ATTACKS + "/#", ATTACKS_ID);
        sURIMatcher.addURI(AUTHORITY, BASE_PATH_EVOLUTIONS, EVOLUTIONS);
        sURIMatcher.addURI(AUTHORITY, BASE_PATH_EVOLUTIONS + "/#", EVOLUTIONS_ID);
    }

    private DigimonContentProvider()
    {

    }
    public static DigimonContentProvider getInstance() {
        if (instance == null)
            instance = new DigimonContentProvider();
        return instance;
    }
    @Override
    public boolean onCreate() {
        Context ctx = MyApp.getContext();
        dbHelper = DBHelper.getInstance(ctx);

        dbHelper.insertDigimon("Guilmon", "Guilmon", "Child/Rookie", "Virus", "Dinosaur", "TRUE","R.mipmap.guilmon.jpg");
        dbHelper.insertDigimon("Growmon", "Growlmon", "Adult/Champion", "Virus", "Bigger Dinosaur", "FALSE","R.mipmap.growmon.jpg");
        dbHelper.insertDigimon("Terriermon", "terriermon", "Child/Rookie", "Vaccine", "Dogbunny", "FALSE","R.mipmap.terriermon.jpg");
        dbHelper.insertDigimon("Galgomon", "Gargomon", "Adult/Champion", "Vaccine", "Gunbunny", "FALSE","R.mipmap.galgomon.jpg");
        dbHelper.insertDigimon("Kyubimon", "Kyubimon", "Adult/Champion", "Data", "9-Tailed Fox", "FALSE","R.mipmap.kyubimon.jpg");
        dbHelper.insertDigimon("Taomon", "Taomon", "Perfect/Ultimate", "Data", "Kitsune Miko", "FALSE","R.mipmap.taomon.jpg");
        dbHelper.insertDigimon("Impmon", "Impmon", "Child/Rookie", "Virus", "Kid in a purple onesie", "FALSE","R.mipmap.impmon.jpg");
        dbHelper.insertDigimon("Beelzebumon", "Beelzemon", "Ultimate/Mega", "Virus", "Demon Lord of Gluttony", "FALSE","R.mipmap.beelzebumon.jpg");

        presentDigimon[460]  = true; presentDigimon[454]  = true;
        presentDigimon[1019] = true; presentDigimon[374]  = true;
        presentDigimon[572]  = true; presentDigimon[1013] = true;
        presentDigimon[507]  = true; presentDigimon[100]  = true;

        dbHelper.insertEvolution("Guilmon", "Growmon", "");
        dbHelper.insertEvolution("Terriermon", "Galgomon","");
        dbHelper.insertEvolution("Kyubimon", "Taomon","");
        dbHelper.insertEvolution("Impmon", "Beelzebumon", "(Warp Evolution)");

        dbHelper.insertAttack("Fireball", "Pyro Sphere", "Guilmon", "Explosive Fireball");
        dbHelper.insertAttack("Rock Breaker", "Rock Breaker", "Guilmon", "Claw Swipe");
        dbHelper.insertAttack("Exhaust Flame", "Pyro Blaster", "Growmon", "Fire Laser");
        dbHelper.insertAttack("Plasma Blade", "Dragon Slash", "Growmon", "Forearm Blades");
        dbHelper.insertAttack("Blazing Fire", "Bunny Blast", "Terriermon", "Energy Blast");
        dbHelper.insertAttack("Petit Twister", "Terrier Tornado", "Terriermon", "Throws Tornado");
        dbHelper.insertAttack("Gatling Arm", "Gargo Laser", "Galgomon", "Fires Guns");
        dbHelper.insertAttack("Dum Dum Upper", "Bunny Pummel", "Galgomon", "Fires Guns While Punching");
        dbHelper.insertAttack("Koenryu", "Dragon Wheel", "Kyubimon", "Fire Dragon");
        dbHelper.insertAttack("Onibidama", "Fox-Tail Inferno", "Kyubimon", "Fireballs from the tails");
        dbHelper.insertAttack("Bonhitsusen", "Talisman of Light", "Taomon", "Energy Seal Laser");
        dbHelper.insertAttack("Oṃ", "Talisman Spell", "Taomon", "Makes a dome shield");
        dbHelper.insertAttack("Night of Fire", "Badaboom", "Impmon", "Mini-Fireballs");
        dbHelper.insertAttack("Pillar of Fire", "", "Impmon", "Wall of Flames");
        dbHelper.insertAttack("Double Impact", "Double Impact", "Beelzebumon", "Fires two bullets");
        dbHelper.insertAttack("Darkness Claw", "", "Beelzebumon", "Kills Leomon");
        db = dbHelper.getWritableDatabase();
        return false;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        Uri _uri = null;
        switch (sURIMatcher.match(uri)) {
            case DIGIMON:
                long _ID1 = db.insert(DigimonTable.DIGIMON_TABLE_NAME, "", values);
                if (_ID1 > 0) {
                    _uri = ContentUris.withAppendedId(CONTENT_URI_DIGIMON, _ID1);
                    MyApp.getContext().getContentResolver().notifyChange(_uri, null);
                }
                break;
            case ATTACKS:
                long _ID2 = db.insert(AttacksTable.ATTACKS_TABLE_NAME, "", values);
                if (_ID2 > 0) {
                    _uri = ContentUris.withAppendedId(CONTENT_URI_ATTACKS, _ID2);
                    MyApp.getContext().getContentResolver().notifyChange(_uri, null);
                }
                break;
            case EVOLUTIONS:
                long _ID3 = db.insert(EvolutionsTable.EVOLUTIONS_TABLE_NAME, "", values);
                if (_ID3 > 0) {
                    _uri = ContentUris.withAppendedId(CONTENT_URI_EVOLUTIONS, _ID3);
                    MyApp.getContext().getContentResolver().notifyChange(_uri, null);
                }
                break;
            default:
                throw new SQLException("Failed to insert row into " + uri);
        }
        MyApp.getContext().getContentResolver().notifyChange(uri, null);
        return _uri;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();

        int uriType = sURIMatcher.match(uri);

        checkColumns(projection, uriType);

        queryBuilder.setTables(DigimonTable.DIGIMON_TABLE_NAME + ", " + EvolutionsTable.EVOLUTIONS_TABLE_NAME + ", " + AttacksTable.ATTACKS_TABLE_NAME);

        switch (uriType) {
            case DIGIMON:
                break;
            case DIGIMON_ID:
                queryBuilder.appendWhere(DigimonTable.DIGIMON_COLUMN_ID+"="+uri.getLastPathSegment());
            case ATTACKS:
                break;
            case ATTACKS_ID:
                queryBuilder.appendWhere(AttacksTable.ATTACKS_COLUMN_ID+"="+uri.getLastPathSegment());
            case EVOLUTIONS:
                break;
            case EVOLUTIONS_ID:
                queryBuilder.appendWhere(EvolutionsTable.EVOLUTIONS_COLUMN_ID+"="+uri.getLastPathSegment());
            default:
                throw new IllegalArgumentException("Unknown URI: "+ uri);
        }
        Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
        cursor.setNotificationUri(MyApp.getContext().getContentResolver(), uri);

        return cursor;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        int uriType = sURIMatcher.match(uri);
        int rowsDeleted = 0;
        switch (uriType) {
            case DIGIMON:
                rowsDeleted = db.delete(DigimonTable.DIGIMON_TABLE_NAME, selection, selectionArgs);
                break;
            case DIGIMON_ID:
                String id1 = uri.getLastPathSegment();
                if (TextUtils.isEmpty(selection)) {
                    rowsDeleted = db.delete(
                            DigimonTable.DIGIMON_TABLE_NAME,
                            DigimonTable.DIGIMON_COLUMN_ID + "=" + id1,
                            null);
                } else {
                    rowsDeleted = db.delete(
                            DigimonTable.DIGIMON_TABLE_NAME,
                            DigimonTable.DIGIMON_COLUMN_ID + "=" + id1
                                    + " and " + selection,
                            selectionArgs);
                }
                break;
            case ATTACKS:
                rowsDeleted = db.delete(AttacksTable.ATTACKS_TABLE_NAME, selection, selectionArgs);
                break;
            case ATTACKS_ID:
                String id2 = uri.getLastPathSegment();
                if (TextUtils.isEmpty(selection)) {
                    rowsDeleted = db.delete(
                            AttacksTable.ATTACKS_TABLE_NAME,
                            AttacksTable.ATTACKS_COLUMN_ID + "=" + id2,
                            null);
                } else {
                    rowsDeleted = db.delete(
                            AttacksTable.ATTACKS_TABLE_NAME,
                            AttacksTable.ATTACKS_COLUMN_ID + "=" + id2
                                    + " and " + selection,
                            selectionArgs);
                }
                break;
            case EVOLUTIONS:
                rowsDeleted = db.delete(EvolutionsTable.EVOLUTIONS_TABLE_NAME, selection, selectionArgs);
                break;
            case EVOLUTIONS_ID:
                String id3 = uri.getLastPathSegment();
                if (TextUtils.isEmpty(selection)) {
                    rowsDeleted = db.delete(
                            EvolutionsTable.EVOLUTIONS_TABLE_NAME,
                            EvolutionsTable.EVOLUTIONS_COLUMN_ID + "=" + id3,
                            null);
                } else {
                    rowsDeleted = db.delete(
                            EvolutionsTable.EVOLUTIONS_TABLE_NAME,
                            EvolutionsTable.EVOLUTIONS_COLUMN_ID + "=" + id3
                                    + " and " + selection,
                            selectionArgs);
                }
                break;
            default:
                throw new IllegalArgumentException("Unknown URI: " + uri);
        }
        MyApp.getContext().getContentResolver().notifyChange(uri, null);
        return rowsDeleted;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {

        int uriType = sURIMatcher.match(uri);
        int rowsUpdated = 0;
        switch (uriType) {
            case DIGIMON:
                rowsUpdated = db.update(DigimonTable.DIGIMON_TABLE_NAME,
                        values,
                        selection,
                        selectionArgs);
                break;
            case DIGIMON_ID:
                String id1 = uri.getLastPathSegment();
                if (TextUtils.isEmpty(selection)) {
                    rowsUpdated = db.update(DigimonTable.DIGIMON_TABLE_NAME,
                            values,
                            DigimonTable.DIGIMON_COLUMN_ID + "=" + id1,
                            null);
                } else {
                    rowsUpdated = db.update(DigimonTable.DIGIMON_TABLE_NAME,
                            values,
                            DigimonTable.DIGIMON_COLUMN_ID + "=" + id1
                                    + " and "
                                    + selection,
                            selectionArgs);
                }
                break;
            case ATTACKS:
                rowsUpdated = db.update(AttacksTable.ATTACKS_TABLE_NAME,
                        values,
                        selection,
                        selectionArgs);
                break;
            case ATTACKS_ID:
                String id2 = uri.getLastPathSegment();
                if (TextUtils.isEmpty(selection)) {
                    rowsUpdated = db.update(AttacksTable.ATTACKS_TABLE_NAME,
                            values,
                            AttacksTable.ATTACKS_COLUMN_ID + "=" + id2,
                            null);
                } else {
                    rowsUpdated = db.update(AttacksTable.ATTACKS_TABLE_NAME,
                            values,
                            AttacksTable.ATTACKS_COLUMN_ID + "=" + id2
                                    + " and "
                                    + selection,
                            selectionArgs);
                }
                break;
            case EVOLUTIONS:
                rowsUpdated = db.update(EvolutionsTable.EVOLUTIONS_TABLE_NAME,
                        values,
                        selection,
                        selectionArgs);
                break;
            case EVOLUTIONS_ID:
                String id3 = uri.getLastPathSegment();
                if (TextUtils.isEmpty(selection)) {
                    rowsUpdated = db.update(EvolutionsTable.EVOLUTIONS_TABLE_NAME,
                            values,
                            EvolutionsTable.EVOLUTIONS_COLUMN_ID + "=" + id3,
                            null);
                } else {
                    rowsUpdated = db.update(EvolutionsTable.EVOLUTIONS_TABLE_NAME,
                            values,
                            EvolutionsTable.EVOLUTIONS_COLUMN_ID + "=" + id3
                                    + " and "
                                    + selection,
                            selectionArgs);
                }
                break;
            default:
                throw new IllegalArgumentException("Unknown URI: " + uri);
        }
        MyApp.getContext().getContentResolver().notifyChange(uri, null);
        return rowsUpdated;
    }
    private void checkColumns(String[] projection, int uri) {
        HashSet<String> availableColumns;
        String[] availableDigimon = { DigimonTable.DIGIMON_COLUMN_ID,
                DigimonTable.DIGIMON_COLUMN_NAME, DigimonTable.DIGIMON_COLUMN_DUB_NAME,
                DigimonTable.DIGIMON_COLUMN_LEVEL, DigimonTable.DIGIMON_COLUMN_ATTRIBUTE,
                DigimonTable.DIGIMON_COLUMN_DESCRIPTION, DigimonTable.DIGIMON_COLUMN_FAVOURITE,
                DigimonTable.DIGIMON_COLUMN_PATH};
        String[] availableAttacks = {AttacksTable.ATTACKS_COLUMN_ID, AttacksTable.ATTACKS_COLUMN_NAME,
                AttacksTable.ATTACKS_COLUMN_DUB_NAME, AttacksTable.ATTACKS_COLUMN_DIGIMON,
                AttacksTable.ATTACKS_COLUMN_DESCRIPTION};
        String[] availableEvolutions = {EvolutionsTable.EVOLUTIONS_COLUMN_ID,EvolutionsTable.EVOLUTIONS_COLUMN_FROM,
                EvolutionsTable.EVOLUTIONS_COLUMN_TO, EvolutionsTable.EVOLUTIONS_COLUMN_CONDITIONS};
        if (projection != null) {
            HashSet<String> requestedColumns = new HashSet<String>(
                    Arrays.asList(projection));
            switch(uri){
                case DIGIMON:
                case DIGIMON_ID: availableColumns = new HashSet<String>(Arrays.asList(availableDigimon));
                    break;
                case ATTACKS:
                case ATTACKS_ID: availableColumns = new HashSet<String>(Arrays.asList(availableAttacks));
                    break;
                case EVOLUTIONS:
                case EVOLUTIONS_ID: availableColumns = new HashSet<String>(Arrays.asList(availableEvolutions));
                    break;
                default: availableColumns = new HashSet<String>(Arrays.asList(availableDigimon));
            }
            // check if all columns which are requested are available
            if (!availableColumns.containsAll(requestedColumns)) {
                throw new IllegalArgumentException(
                        "Unknown columns in projection");
            }
        }
    }

    public Cursor defaultMainMenu()
    {
        Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_DIGIMON, new String[]{DigimonTable.DIGIMON_COLUMN_NAME, DigimonTable.DIGIMON_COLUMN_FAVOURITE}, null, null, DigimonTable.DIGIMON_COLUMN_NAME + " ASC");
        int dummy = cursor.getCount();
        return cursor;

    }
    public Cursor searchMenuQuery(String search)
    {
        Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_DIGIMON,new String[] {DigimonTable.DIGIMON_COLUMN_NAME,DigimonTable.DIGIMON_COLUMN_FAVOURITE},DigimonTable.DIGIMON_COLUMN_NAME+" = '?'",new String[]{search},DigimonTable.DIGIMON_COLUMN_NAME+" ASC");
        int dummy = cursor.getCount();
        return cursor;
    }
    public Cursor favouritesMenuQuery()
    {
        Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_DIGIMON,new String[] {DigimonTable.DIGIMON_COLUMN_NAME},DigimonTable.DIGIMON_COLUMN_FAVOURITE+" = true",null,DigimonTable.DIGIMON_COLUMN_NAME+" ASC");
        int dummy = cursor.getCount();
        return cursor;
    }
    public Cursor digimonProfileQuery(String name)
    {
        Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_DIGIMON,null,DigimonTable.DIGIMON_COLUMN_NAME+" = '?'",new String[]{name},null);
        int dummy = cursor.getCount();
        return cursor;
    }
    public Cursor digimonAttacksQuery(String name)
    {
        Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_ATTACKS,null,AttacksTable.ATTACKS_COLUMN_DIGIMON+" = '?'",new String[]{name},null);
        int dummy = cursor.getCount();
        return cursor;
    }
    public Cursor digimonEvolutionFromQuery(String name)
    {
        Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_EVOLUTIONS,null,EvolutionsTable.EVOLUTIONS_COLUMN_FROM+" = '?'",new String[]{name},null);
        int dummy = cursor.getCount();
        return cursor;
    }
    public Cursor digimonEvolutionToQuery(String name)
    {
        Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_EVOLUTIONS,null,EvolutionsTable.EVOLUTIONS_COLUMN_TO+" = '?'",new String[]{name},null);
        int dummy = cursor.getCount();
        return cursor;
    }
}

这是 Logcat 结果:

Process: com.corvus.corvusenterprises.digimonapp, PID: 12198
              java.lang.RuntimeException: Unable to get provider com.corvus.corvusenterprises.digimonapp.DigimonContentProvider: java.lang.NullPointerException
                  at android.app.ActivityThread.installProvider(ActivityThread.java:5084)
                  at android.app.ActivityThread.installContentProviders(ActivityThread.java:4673)
                  at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4613)
                  at android.app.ActivityThread.access00(ActivityThread.java:141)
                  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1298)
                  at android.os.Handler.dispatchMessage(Handler.java:102)
                  at android.os.Looper.loop(Looper.java:136)
                  at android.app.ActivityThread.main(ActivityThread.java:5333)
                  at java.lang.reflect.Method.invokeNative(Native Method)
                  at java.lang.reflect.Method.invoke(Method.java:515)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:895)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:711)
                  at dalvik.system.NativeStart.main(Native Method)
               Caused by: java.lang.NullPointerException
                  at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
                  at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
                  at com.corvus.corvusenterprises.digimonapp.DigimonContentProvider.onCreate(DigimonContentProvider.java:62)
                  at android.content.ContentProvider.attachInfo(ContentProvider.java:1616)
                  at android.content.ContentProvider.attachInfo(ContentProvider.java:1587)
                  at android.app.ActivityThread.installProvider(ActivityThread.java:5081)
                  at android.app.ActivityThread.installContentProviders(ActivityThread.java:4673) 
                  at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4613) 
                  at android.app.ActivityThread.access00(ActivityThread.java:141) 
                  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1298) 
                  at android.os.Handler.dispatchMessage(Handler.java:102) 
                  at android.os.Looper.loop(Looper.java:136) 
                  at android.app.ActivityThread.main(ActivityThread.java:5333) 
                  at java.lang.reflect.Method.invokeNative(Native Method) 
                  at java.lang.reflect.Method.invoke(Method.java:515) 
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:895) 
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:711) 
                  at dalvik.system.NativeStart.main(Native Method) 

这里是 DBHelper 代码,希望对您有所帮助:

    package com.corvus.corvusenterprises.digimonapp;

    import android.content.ContentValues;
    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;

    import static com.corvus.corvusenterprises.digimonapp.DigimonContentProvider.CONTENT_URI_ATTACKS;
    import static com.corvus.corvusenterprises.digimonapp.DigimonContentProvider.CONTENT_URI_DIGIMON;
    import static com.corvus.corvusenterprises.digimonapp.DigimonContentProvider.CONTENT_URI_EVOLUTIONS;

    /**
     * Created by Jack on 01/05/2017.
     */

    public class DBHelper extends SQLiteOpenHelper {
        public static final String[]digimonArray = {
                "Gigantic array of names"};
        private static final String DATABASE_NAME = "DigimonDatabase.db";
    private static final int version = 1;
    private static DBHelper instance;
    public static boolean[]presentDigimon = new boolean[digimonArray.length];
    private DBHelper(Context context) {
        super(context, DATABASE_NAME, null, version);
    }
    public static DBHelper getInstance(Context ctx) {
        if (instance == null)
            instance = new DBHelper(ctx);
        return instance;
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        DigimonTable.onCreate(db);
        AttacksTable.onCreate(db);
        EvolutionsTable.onCreate(db);
    }
    public void onUpgrade(SQLiteDatabase db, int oldver, int newVer)
    {
        DigimonTable.onUpgrade(db,oldver,newVer);
        AttacksTable.onUpgrade(db,oldver,newVer);
        EvolutionsTable.onUpgrade(db,oldver,newVer);
    }
    public void insertDigimon(String name, String dub_name, String level, String attribute, String description, String favourite, String path)
    {
        DigimonContentProvider dcp = DigimonContentProvider.getInstance();
        ContentValues values = new ContentValues();
        values.put(DigimonTable.DIGIMON_COLUMN_NAME,name);
        values.put(DigimonTable.DIGIMON_COLUMN_DUB_NAME,dub_name);
        values.put(DigimonTable.DIGIMON_COLUMN_LEVEL,level);
        values.put(DigimonTable.DIGIMON_COLUMN_ATTRIBUTE,attribute);
        values.put(DigimonTable.DIGIMON_COLUMN_DESCRIPTION,description);
        values.put(DigimonTable.DIGIMON_COLUMN_FAVOURITE, favourite);
        values.put(DigimonTable.DIGIMON_COLUMN_PATH,path);
        dcp.insert(CONTENT_URI_DIGIMON, values);
    }
    public void insertAttack(String name, String dub_name, String digimon, String description)
    {
        DigimonContentProvider dcp = DigimonContentProvider.getInstance();
        ContentValues values = new ContentValues();
        values.put(AttacksTable.ATTACKS_COLUMN_NAME, name);
        values.put(AttacksTable.ATTACKS_COLUMN_DUB_NAME,dub_name);
        values.put(AttacksTable.ATTACKS_COLUMN_DIGIMON, digimon);
        values.put(AttacksTable.ATTACKS_COLUMN_DESCRIPTION, description);
        dcp.insert(CONTENT_URI_ATTACKS, values);
    }
    public void insertEvolution(String from, String to, String conditions)
    {
        DigimonContentProvider dcp = DigimonContentProvider.getInstance();
        ContentValues values = new ContentValues();
        values.put(EvolutionsTable.EVOLUTIONS_COLUMN_TO,to);
        values.put(EvolutionsTable.EVOLUTIONS_COLUMN_FROM,from);
        values.put(EvolutionsTable.EVOLUTIONS_COLUMN_CONDITIONS,conditions);
        dcp.insert(CONTENT_URI_EVOLUTIONS, values);
    }
}

感谢所有帮助。如果您需要更多信息,请告诉我。 (已编辑):正在开发新版本。代码已更新。 (编辑 2):修复了递归调用可能存在的问题。

它抛出一个 NullPointerException,因为您试图直接访问您的 ContentProvider 方法,而不是使用 ContentResolver 方法。

您可以抽象化您在 ContentProvider 中编写的代码,以便在另一个 class 中访问它。这次使用 ContentResolver 相同的实例。

编辑:
也许你的问题是你的 dbHelper 不是单例,你正在通过 insert() 方法中的 dbHelper.getInstance(getContext) 创建它的另一个实例。
尝试仅在 onCreate() 方法中而不是在其他方法中获取 dbHelper 的新实例。

你可以使用这个例子:MoviesContentProvider.java

I know for a fact that the Context isn't null

你怎么知道的? MyApp.getContext() 我觉得很奇怪。

尝试将上下文提供给 ContentProvider

private Context mContext;

private DigimonContentProvider(Context context)
{
    this.mContext = context;
}

private DigimonContentProvider() { }


public static DigimonContentProvider getInstance(Context context) {
    if (instance == null)
        instance = new DigimonContentProvider(context);
    return instance;
}

@Override
public boolean onCreate() {
    dbHelper = DBHelper.getInstance(this.mContext);

但是,您不需要 ContentProvider 来拥有数据库,因此请尝试让数据库在没有它的情况下工作。