8

我有一个问题,我不知道如何解决它。我的应用程序中的一个活动有多个AsyncTasks 访问单个SQLiteOpenHelper. 我初始化并打开助手,onCreate()然后将其关闭onStop()。我还检查它是否已在onResume().

自从我发布了我的应用程序以来doInBackground,我在尝试访问 DB 帮助程序时收到了许多带有 Null Exception 的错误。我知道这是因为数据库在被调用onStop()之前关闭(),这很公平。doInBackground

我的问题是,我应该在哪里关闭数据库连接?在 Activity 中使用 DB 助手的单个实例并从多个线程()访问它是否正确AsyncTasks?或者我应该为每个使用单独的数据库助手实例AsyncTask

这是我的活动的简化骨架:

public class MyActivity extends Activity{
    private DbHelper mDbHelper;
    private ArrayList<ExampleObject> objects;

    @Override
    public void onStop(){
        super.onStop();
        if(mDbHelper != null){
            mDbHelper.close();
            mDbHelper = null;
        }
    }

    @Override
    public void onResume(){
        super.onResume();
        if(mDbHelper == null){
            mDbHelper = new DbHelper(this);
            mDbHelper.open();
        }
    }

    @Override 
    public void onCreate(Bundle icicle) { 
        super.onCreate(icicle); 
        DbHelper mDbHelper = new DbHelper(this);
        mDbHelper.open();
    }

    private class DoSomething extends AsyncTask<String, Void, Void> {

        @Override
        protected Void doInBackground(String... arg0) {
            objects = mDbHelper.getMyExampleObjects();
            return null;
        }

        @Override
        protected void onPostExecute(final Void unused){
            //update UI with my objects
        }
    }

    private class DoSomethingElse extends AsyncTask<String, Void, Void> {

        @Override
        protected Void doInBackground(String... arg0) {
            objects = mDbHelper.getSortedObjects();
            return null;
        }

        @Override
        protected void onPostExecute(final Void unused){
            //update UI with my objects
        }
    }
}
4

3 回答 3

11

您不需要为每个活动管理数据库连接。您可以在 android.app.Application 的实例中执行此操作,并使用此实例访问 db。像这样的东西:

public class MyApplication extends Application {

    // Synchronized because it's possible to get a race condition here
    // if db is accessed from different threads. This synchronization can be optimized
    // thought I wander if it's necessary
    public synchronized static SQLiteDatabase db() {
        if(self().mDbOpenHelper == null) {
            self().mDbOpenHelper = new MyDbOpenHelper();
        }
        return self().mDbOpenHelper.getWritableDatabase();
    }

    public static Context context() {
        return self();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mSelf = this;
    }

    private static MyApplication self() {
        if (self == null) throw new IllegalStateException();
        return mSelf;
    }

    private MyDbOpenHelper mDbOpenHelper;

    private static MyApplication mSelf;
}

这样您就可以确保您的 Db 始终是可访问的。

是的,拥有一个 Db 助手实例是一种很好的做法。默认情况下会为您进行线程同步。

于 2011-09-22T11:44:40.207 回答
5

最好使用单个DB Helper. 问题是当用户离开时Activity关闭DBAsyncTask可能仍然运行。DB因此,当您尝试访问它时,您应该检查它是否不为空,如果是,null这可能意味着您Activity已被破坏并且cancel该任务。

于 2011-09-22T11:35:34.237 回答
1

您提到您在关闭数据库之前取消了 AsyncTask。但是您应该记住,取消 AsyncTask 只是发出要取消任务的信号,您需要检查 doInBackground() 中的 isCancelled() 并执行必要的停止数据库操作。

在关闭数据库之前,您需要检查 getStatus() 以确保 AsyncTask 已停止。

于 2011-09-22T12:03:51.447 回答