我的应用程序崩溃是因为我错误地实现了我的数据库单例吗?
Is my app crashing because I've mis-implemented my database singleton?
因此,只要我积极使用 phone,我的应用程序似乎就可以正常工作。我可以旋转屏幕,关闭应用程序,然后重新打开它,无论如何,没问题。
但是如果我按下 home/back 按钮并将应用程序发送到后台,然后如果我晚上睡觉,当我在几个小时后醒来并尝试再次打开该应用程序时,它立即崩溃。我不知道是什么导致了这个错误,但我认为它与 NullPointerException
(此时我存在的祸根)有关,因为 Android 已决定释放一些内存。
我参考了这张图:
所以当我将应用程序发送到后台时,它会转到 onStop()
,然后 Android 最终可能会释放一些内存并终止进程,所以当我再次打开应用程序时,它尝试调用 onCreate()
,但现在 onCreate()
崩溃了。这对我来说毫无意义。
我能想到的唯一另一个原因是我在我的应用程序中使用了一个 SQLite3
数据库单例,它不知何故被 Android 释放内存所吞噬。在我所有 Activities
和 Fragments
的 onCreate()
方法中,我通常调用 mDatabaseHelper = DatabaseHelper.getInstance(context);
(其中 context
通常是 this
如果我是在 Activity
中,如果我在 Fragment
中,则在 getActivity()
中。
这是我的 DatabaseHelper
class:
public class DatabaseHelper extends SQLiteOpenHelper {
private static volatile SQLiteDatabase mDatabase;
private static DatabaseHelper mInstance = null;
private static Context mContext;
//... various constant fields here ...
public static synchronized DatabaseHelper getInstance(Context context){
if (mInstance == null){
mInstance = new DatabaseHelper(context.getApplicationContext());
}
return mInstance;
}
private DatabaseHelper(Context context){
super(context, DB_NAME, null, DB_VERSION);
mContext = context;
}
public void open() throws SQLException {
mDatabase = getWritableDatabase();
}
public void close(){
mDatabase.close();
}
//... other functions here ...
}
在我的启动器 activity (MainActivity
) 中,我这样做:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DatabaseHelper databaseHelper = DatabaseHelper.getInstance(this);
databaseHelper.open();
Intent intent = new Intent(this, AnotherActivity.class);
startActivity(intent);
finish();
}
}
这是我唯一一次在整个应用程序中调用 open()
。我从不在任何地方打电话给 close()
。
这是否解释了导致我的应用程序崩溃的原因?由于我在我的 onCreate
方法中调用了 getInstance()
(当我在长时间空闲后恢复应用程序时调用它),这让我怀疑该函数出现问题。 Android 是否可以通过某种方式破坏 "Application context" 来释放内存? mDatabase
是否有可能以某种方式设置为 null
?我还需要做些什么来确保我正确地实施了这个数据库?
这通常发生在 Android 中的单例模式中。你可以在这里阅读一些相关内容
Static singleton lifetime in Android
这在过去一直困扰着我。我可能会在创建数据库后立即将您对 getInstance 方法中的 if 语句的打开移动到 运行。这样,如果 Android 由于您的应用程序长时间处于空闲状态而清理内存,它也会在下次返回时重新打开数据库。即:
public static synchronized DatabaseHelper getInstance(Context context){
if (mInstance == null){
mInstance = new DatabaseHelper(context.getApplicationContext());
try {
mInstance.open();
} catch (Exception exe) {}
}
return mInstance;
}
因此,只要我积极使用 phone,我的应用程序似乎就可以正常工作。我可以旋转屏幕,关闭应用程序,然后重新打开它,无论如何,没问题。
但是如果我按下 home/back 按钮并将应用程序发送到后台,然后如果我晚上睡觉,当我在几个小时后醒来并尝试再次打开该应用程序时,它立即崩溃。我不知道是什么导致了这个错误,但我认为它与 NullPointerException
(此时我存在的祸根)有关,因为 Android 已决定释放一些内存。
我参考了这张图:
所以当我将应用程序发送到后台时,它会转到 onStop()
,然后 Android 最终可能会释放一些内存并终止进程,所以当我再次打开应用程序时,它尝试调用 onCreate()
,但现在 onCreate()
崩溃了。这对我来说毫无意义。
我能想到的唯一另一个原因是我在我的应用程序中使用了一个 SQLite3
数据库单例,它不知何故被 Android 释放内存所吞噬。在我所有 Activities
和 Fragments
的 onCreate()
方法中,我通常调用 mDatabaseHelper = DatabaseHelper.getInstance(context);
(其中 context
通常是 this
如果我是在 Activity
中,如果我在 Fragment
中,则在 getActivity()
中。
这是我的 DatabaseHelper
class:
public class DatabaseHelper extends SQLiteOpenHelper {
private static volatile SQLiteDatabase mDatabase;
private static DatabaseHelper mInstance = null;
private static Context mContext;
//... various constant fields here ...
public static synchronized DatabaseHelper getInstance(Context context){
if (mInstance == null){
mInstance = new DatabaseHelper(context.getApplicationContext());
}
return mInstance;
}
private DatabaseHelper(Context context){
super(context, DB_NAME, null, DB_VERSION);
mContext = context;
}
public void open() throws SQLException {
mDatabase = getWritableDatabase();
}
public void close(){
mDatabase.close();
}
//... other functions here ...
}
在我的启动器 activity (MainActivity
) 中,我这样做:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DatabaseHelper databaseHelper = DatabaseHelper.getInstance(this);
databaseHelper.open();
Intent intent = new Intent(this, AnotherActivity.class);
startActivity(intent);
finish();
}
}
这是我唯一一次在整个应用程序中调用 open()
。我从不在任何地方打电话给 close()
。
这是否解释了导致我的应用程序崩溃的原因?由于我在我的 onCreate
方法中调用了 getInstance()
(当我在长时间空闲后恢复应用程序时调用它),这让我怀疑该函数出现问题。 Android 是否可以通过某种方式破坏 "Application context" 来释放内存? mDatabase
是否有可能以某种方式设置为 null
?我还需要做些什么来确保我正确地实施了这个数据库?
这通常发生在 Android 中的单例模式中。你可以在这里阅读一些相关内容
Static singleton lifetime in Android
这在过去一直困扰着我。我可能会在创建数据库后立即将您对 getInstance 方法中的 if 语句的打开移动到 运行。这样,如果 Android 由于您的应用程序长时间处于空闲状态而清理内存,它也会在下次返回时重新打开数据库。即:
public static synchronized DatabaseHelper getInstance(Context context){
if (mInstance == null){
mInstance = new DatabaseHelper(context.getApplicationContext());
try {
mInstance.open();
} catch (Exception exe) {}
}
return mInstance;
}