android Sqlite IllegalStateException при выполнении AsyncTask

#android #sqlite #android-asynctask #illegalstateexception

#Android #sqlite #android-asynctask #исключение illegalstateexception

Вопрос:

Всем доброго дня.

Итак, у меня есть AsyncTask, который вычисляет размытие по Гауссу из изображения. Исходные данные изображения извлекаются из SQLite с помощью Blob-поля, также отфильтрованное изображение сохраняется в SQLite. Вот код (setQuizData — это функция, которая это делает):

 public class SaveFilterTask  extends AsyncTask<Void, Void, Void>{

private Context mContext;
private Context mApplicationContext;
private Quiz mQuiz;     

public SaveFilterTask(Context context, Quiz quiz, Context applicationContext) {
    super();
    this.mContext = context;
    this.mApplicationContext = applicationContext;
    this.mQuiz = quiz;
}

@Override
protected Void doInBackground(Void... arg0) {
    try {
        setQuizData(mQuiz);
    } catch (UnsupportedEncodingException e) {
        cancel(true);
    }
    return null;
}

@Override
protected void onCancelled() {
    Toast toast = Toast.makeText(mContext, R.string.error_loading_quiz, Toast.LENGTH_SHORT);
    toast.setGravity(Gravity.CENTER, 0, 0);
    toast.show();
}

@Override
protected void onPreExecute() {
    if(!((Activity)mContext).isFinishing()){
        ((MainActivity)mContext).showDialog();
    }
}

protected void onPostExecute(Void args) {

    if(!((Activity)mContext).isFinishing()){
        ((MainActivity)mContext).hideDialog();
    }

    Intent solveQuizIntent = new Intent(mContext, SolveQuizActivity.class);
    solveQuizIntent.putExtra(
            QuizConstants.KEY_PARCELABLE_FINISHED_QUIZ, mQuiz);
    solveQuizIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    mContext.startActivity(solveQuizIntent);
}

private void setQuizData(Quiz quiz) throws UnsupportedEncodingException {
    if(quiz.getType().equals(QuizConstants.TYPE_PHOTO)){
        QuizDataSource quizdatasource = new QuizDataSource(mApplicationContext);
        quizdatasource.open();
        String data = quizdatasource.getData(quiz.getId());
        quizdatasource.close();
        QuizDataSource quizdatasource2 = new QuizDataSource(mApplicationContext);
        quizdatasource2.open();
        String filterData = quizdatasource2.getDataFilter(quiz.getId());
        quizdatasource2.close();

        String filter = quiz.getFilter();
        if(filter != null){
            if(!filter.equals(QuizConstants.FILTER_DEFAULT)){
                Bitmap original = decodeImage(data);                                    
                if(filterData == null){         
                    data = FilterManager.applyFilter(original, quiz.getFilter());
                    Log.d("FilterManager","Data: "  data);
                    Log.d("FilterManager","Id: "  quiz.getId());
                    QuizDataSource quizdatasourceW = new QuizDataSource(mApplicationContext);
                    quizdatasourceW.open();
                    quizdatasourceW.setDataFilter(quiz.getId(), data);
                    quizdatasourceW.close();
                }                   
            }
        }           
    }
}


private static Bitmap decodeImage(String data) {         
    byte[] b = Base64.decode(data, Base64.DEFAULT);                 
    return BitmapFactory.decodeByteArray(b, 0, b.length);
}

}
  

Эта задача вызывается из моей деятельности, например:

 SaveFilterTask sftask = new SaveFilterTask(this, quiz, getApplicationContext());
sftask.execute();
  

Я не знаю, почему иногда (и случайным образом) Я получаю эту ошибку:

 0java.lang.RuntimeException: An error occured while executing doInBackground()
1at android.os.AsyncTask$3.done(AsyncTask.java:300)
2at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
3at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
4at java.util.concurrent.FutureTask.run(FutureTask.java:242)
5at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
6at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
7at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
8at java.lang.Thread.run(Thread.java:841)
9Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/Data.db
10at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
11at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1156)
12at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1032)
13at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1200)
14at QuizDataSource.getDataFilter(QuizDataSource.java:119)
15at SaveFilterTask.setQuizData(SaveFilterTask.java:82)
16at SaveFilterTask.doInBackground(SaveFilterTask.java:39)
17at SaveFilterTask.doInBackground(SaveFilterTask.java:1)
  

Я пробовал по-разному, используя одно соединение, используя одно соединение для операций чтения и одно для операции записи. Но ошибка сохраняется…

Есть идеи?

Спасибо.

Ответ №1:

Прежде всего, вы не должны каждый раз повторно инициализировать QuazDataSource.

Инициализируйте его в конструкторе и проверьте его с помощью

 if (quizdatasource  == null) {
    quizdatasource = CreateaQuizDataSourceHelper().open;
}
  

Тогда вы всегда должны обязательно закрывать его, даже если он выходит из строя.

 Cursor cursor = null;
try {
  if (quizdatasource  == null) {
 quizdatasource = CreateaQuizDataSourceHelper().open;
  } 
  cursor= quizdatasource.rawQuery(...);
} catch (Exception e) { e.printStackTrace(); }
finally {
  if (quizdatasource != null) { quizdatasource.close(); }
}
  

по крайней мере, убедитесь, что ваши курсоры также закрыты, поместив проверку в блок finally.

 if (cursor != null) { cursor.close; } 
  

тогда вы не должны получать несколько экземпляров.

Вы также должны создать одноэлементный экземпляр вашей базы данных, чтобы убедиться, что к нему обращаются только один раз.

У самого помощника может быть такой открытый метод, чтобы убедиться, что он использует то же соединение.

     public SQLiteDatabase open() {
    SQLiteDatabase sqLiteDatabase = null;
    try {

        try {
            sqLiteDatabase = this.getDatabaseConnection();
        } catch (SQLiteException e) {
            e.printStackTrace();
            DataBaseConnectionPool.DbHelper DbHelper = this.dbHelper;
            if (DbHelper != null) {
                return this.dbHelper.getReadableDatabase();
            }
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
    return sqLiteDatabase;
}