在Service中使用Singleton SQLiteHelper

时间:2016-03-30 17:50:38

标签: java android sqlite android-service intentservice

我有一个在SQLite中存储数据的服务。我希望该服务在应用程序关闭时继续运行。 (向外滑动)但是当销毁应用程序时,getInstance()会返回null。即使申请被关闭,我怎样才能保持活力?

我的数据库单例类:

public class DbManager {
    private static DbManager instance;
    private CipherDbHelper dbHelper;

    private DbManager() {

    }

    private DbManager(Context context, String password) {
        SQLiteDatabase.loadLibs(context);
        dbHelper = new CipherDbHelper(context, password);
    }

    public static void init(Context context, String password) {
        instance = new DbManager(context, password);
    }

    public static DbManager getInstance() {
        if (instance == null) {
            Log.e("DbManager", "Can't access DbManager : instance is null.")
        }
        return instance;
    }

    //Closing
    public void closeDatabase() {
        dbHelper.close();
        dbHelper = null;
        instance = null;
    }

    public <D extends Dao<T, String>, T> D getDAO(Class<T> clz) throws SQLException {
        return dbHelper.getDao(clz);
    }


}

3 个答案:

答案 0 :(得分:1)

步骤1:删除closeDatabase()以及任何调用它的代码。

步骤2:让getDatabase()返回null而不是抛出异常,或让它抛出自定义异常而不是IllegalArgumentException

步骤3:如果服务从其null电话中获得getDatabase()(或者它捕获了您的自定义例外),请让它引发Notification告诉用户“我需要你再次登录“并跳过它应该做的任何工作。

从根本上说,您遇到了一个架构问题:Android进程是短暂的。其结果是在后台使用加密数据库通常是不可能的。一旦流程结束,您将无法访问数据库(使用用户的密码解锁),需要用户再次登录。

您可以使用前台服务(通过startForeground())来减少进程终止的可能性,但这会给用户带来成本(始终可见Notification,可能会导致CPU过多用于非真实背景的工作等。)。

答案 1 :(得分:0)

要在后台运行任务,您需要使用Service

在致电X之前,请致电Y;因为在您调用DBManager.init(context)方法之前,您的实例仍为DBManager.getInstance()

答案 2 :(得分:0)

对于使用单例类来获取帮助程序实例的服务访问SQLite数据库(加密或未加密)的相同问题。以下是我解决问题的方法。只需将服务的上下文传递给SQLiteHelper,再次加载lib并重新生成帮助程序实例。然后,一旦关闭应用程序(通过刷掉它),它就不会被销毁

在我的例子中,我在我的服务的onCreate方法上调用了它:

    DbManager.init(TrackingService.this, "examplePassword"));