Android SQLiteOpenHelper 错误 - 对 super 的调用必须是构造函数中的第一条语句

Android SQLiteOpenHelper Error - Call to super must be the first statement in contructor

首先我要说的是,在问这个问题之前,我已经阅读了很多类似的问题,但是我找不到适合我的情况的任何可能的解决方案。

我正在尝试扩展 SQLiteOpenHelper class,但有 2 个显着差异 -

  1. 我正在使用 SQLCipher(如果我使用 super 构造函数中的顶部)
  2. 正在从 SharedPreferences(这就是为什么,我必须把它放在super之前)

例如,以下构造函数工作正常(我排除了与我的问题无关的导入和函数)-

import net.sqlcipher.Cursor;
import net.sqlcipher.SQLException;
import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteOpenHelper;

public class LocalDBHelper extends SQLiteOpenHelper {
    public static String DB_LOCAL_NAME = "localdata.db";
    public static SQLiteDatabase myDataBase;
    private final Context myContext;

    public LocalDBHelper(Context context) {
        super(context, Environment.getExternalStorageDirectory().toString()+File.separator + "myFolder"
                + "/" + DB_LOCAL_NAME, null, 1);
        this.myContext = context;
        SQLiteDatabase.loadLibs(context);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int i, int i1) {
        onCreate(db);
    }
}

但是,就我而言,我希望允许数据库位置可变(例如,用户可以从“下载”文件夹中使用它,或者如果用户不允许使用外部存储(如 Android 6.0),然后根据情况使用内部存储或使用 getExternalFilesDir())-> 所以,长话短说,我将数据库位置保存在共享首选项中,并尝试通过如下修改构造函数来使用它 -

public QuestionBankDBHelper(Context context) {
        SharedPreferences getPrefs = PreferenceManager
                .getDefaultSharedPreferences(NoContextAvailable); //What should I use here for the context ?
        String getDBLocation = getPrefs.getString("MY_DATABASE_LOCATION", Environment.getExternalStorageDirectory().toString()+File.separator + "myFolder"
                + "/" + DB_LOCAL_NAME);
        super(context, getDBLocation, null, 1);
        this.myContext = context;
        SQLiteDatabase.loadLibs(context);
    }

显然上面修改的构造函数不起作用,并给出了以下两个错误-

  1. 什么上下文可以与 getDefaultSharedPreferences 一起使用?
  2. 对 super 的调用必须是构造函数中的第一条语句。

即使经过大量的试验和搜索,我也想不出如何解决这两个问题,并让我的数据库位置可变。

getDBLocation 代码移动到静态方法中:

private static String getDBLocation(Context context) {
    SharedPreferences getPrefs = PreferenceManager.getDefaultSharedPreferences(context);
    String getDBLocation = getPrefs.getString("MY_DATABASE_LOCATION", 
            Environment.getExternalStorageDirectory().toString() 
                + File.separator + "myFolder" + "/" + DB_LOCAL_NAME);
    return getDBLocation;
}

public QuestionBankDBHelper(Context context) {
    super(context, getDBLocation(context), null, 1);
    this.myContext = context;
    SQLiteDatabase.loadLibs(context);
}

简单回答:

  1. 创建接受上下文作为参数和 returns 数据库路径的静态函数
  2. super作为第一条语句,使用静态函数return作为路径参数

正确的解决方案是删除任何有关在此 class 中查找数据库路径的知识。在构造此 class 之前,您应该进行所有检查、计算、提问,并且仅调用具有定义路径

的此 class 的构造函数