Экземпляр 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 этой задачи.