我的应用程序崩溃是因为我错误地实现了我的数据库单例吗?

Is my app crashing because I've mis-implemented my database singleton?

因此,只要我积极使用 phone,我的应用程序似乎就可以正常工作。我可以旋转屏幕,关闭应用程序,然后重新打开它,无论如何,没问题。

但是如果我按下 home/back 按钮并将应用程序发送到后台,然后如果我晚上睡觉,当我在几个小时后醒来并尝试再次打开该应用程序时,它立即崩溃。我不知道是什么导致了这个错误,但我认为它与 NullPointerException(此时我存在的祸根)有关,因为 Android 已决定释放一些内存。

我参考了这张图:

所以当我将应用程序发送到后台时,它会转到 onStop(),然后 Android 最终可能会释放一些内存并终止进程,所以当我再次打开应用程序时,它尝试调用 onCreate(),但现在 onCreate() 崩溃了。这对我来说毫无意义。

我能想到的唯一另一个原因是我在我的应用程序中使用了一个 SQLite3 数据库单例,它不知何故被 Android 释放内存所吞噬。在我所有 ActivitiesFragmentsonCreate() 方法中,我通常调用 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;
}