Экземпляр Android AsyncTask и SQLite DB
у меня проблема, и я не уверен, как к ней подойти. Активность в моем приложении имеет несколько AsyncTask
s, которые получают доступ к 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
этой задачи.