Экземпляр Android AsyncTask и SQLite DB

у меня проблема, и я не уверен, как к ней подойти. Активность в моем приложении имеет несколько AsyncTasks, которые получают доступ к single SQLiteOpenHelper. Я инициализирую и открываю помощник в onCreate() и я закрываю его в onStop(). Я также проверяю, был ли он инициализирован в onResume().

поскольку я опубликовал свое приложение, я получил количество ошибок с нулевым исключением в doInBackground где я пытаюсь получить доступ к помощнику DB. Я знаю, что это происходит, потому что БД закрыта (onStop() ) просто перед the doInBackground называется, достаточно.

мой вопрос в том, где я должен закрыть соединение с БД? Правильно ли использовать один экземпляр помощника БД в действии и обращаться к нему из нескольких потоков (AsyncTasks)? Или я должен использовать отдельный экземпляр помощника DB для каждого 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
        }
    }
}

3 ответов


вы упомянули, что отменяете AsyncTask перед закрытием БД. Но вы должны иметь в виду, что отмена AsyncTask просто сигнализирует об отмене задачи, и вам нужно проверить isCancelled() в doInBackground() и сделать необходимое, чтобы остановить операции БД.

перед закрытием БД вам необходимо проверить getStatus (), чтобы убедиться, что AsyncTask остановился.


вам не нужно управлять подключением к БД для каждого действия. Вы можете сделать это в экземпляре android.приложение.Применение и доступ к БД с помощью этого экземпляра. Что-то вроде этого:--2-->

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 helper является хорошей практикой. Синхронизация потоков производится для вас по умолчанию.


хорошо использовать один DB Helper. Проблема в том, что когда пользователь оставляет Activity на DB закрыт, но AsyncTask все еще может работать. Поэтому вы должны проверить, что DB не null, когда вы пытаетесь получить к нему доступ, и если это null это может означать, что ваш Activity был разрушен и cancel этой задачи.