Android SQLiteOpenHelper 错误 - 对 super 的调用必须是构造函数中的第一条语句
Android SQLiteOpenHelper Error - Call to super must be the first statement in contructor
首先我要说的是,在问这个问题之前,我已经阅读了很多类似的问题,但是我找不到适合我的情况的任何可能的解决方案。
我正在尝试扩展 SQLiteOpenHelper
class,但有 2 个显着差异 -
- 我正在使用 SQLCipher(如果我使用
super
构造函数中的顶部)
- 我正在从
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);
}
显然上面修改的构造函数不起作用,并给出了以下两个错误-
- 什么上下文可以与
getDefaultSharedPreferences
一起使用?
- 对 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);
}
简单回答:
- 创建接受上下文作为参数和 returns 数据库路径的静态函数
- 将
super
作为第一条语句,使用静态函数return作为路径参数
正确的解决方案是删除任何有关在此 class 中查找数据库路径的知识。在构造此 class 之前,您应该进行所有检查、计算、提问,并且仅调用具有定义路径
的此 class 的构造函数
首先我要说的是,在问这个问题之前,我已经阅读了很多类似的问题,但是我找不到适合我的情况的任何可能的解决方案。
我正在尝试扩展 SQLiteOpenHelper
class,但有 2 个显着差异 -
- 我正在使用 SQLCipher(如果我使用
super
构造函数中的顶部) - 我正在从 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);
}
显然上面修改的构造函数不起作用,并给出了以下两个错误-
- 什么上下文可以与
getDefaultSharedPreferences
一起使用? - 对 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);
}
简单回答:
- 创建接受上下文作为参数和 returns 数据库路径的静态函数
- 将
super
作为第一条语句,使用静态函数return作为路径参数
正确的解决方案是删除任何有关在此 class 中查找数据库路径的知识。在构造此 class 之前,您应该进行所有检查、计算、提问,并且仅调用具有定义路径
的此 class 的构造函数