2013-08-16 4 views
0

Я использую AsyncTask в некоторых из моих Fragment и Activity, и эти работы приятные. Но проблема в том, когда я нажимаю кнопку «Назад» или выхожу из приложения во время выполнения задачи Asynchronous, приложение вылетает. Это мой журнал кот:неполная asynctask сбой мое приложение

08-16 08:15:34.032: E/AndroidRuntime(21957): FATAL EXCEPTION: main 
08-16 08:15:34.032: E/AndroidRuntime(21957): java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 
08-16 08:15:34.032: E/AndroidRuntime(21957): at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1327) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1338) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at me.kaidul.uhunt.MainActivity.selectItem(MainActivity.java:434) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at me.kaidul.uhunt.MainActivity.access$0(MainActivity.java:387) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at me.kaidul.uhunt.MainActivity$GetProblemListTask.onPostExecute(MainActivity.java:680) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at me.kaidul.uhunt.MainActivity$GetProblemListTask.onPostExecute(MainActivity.java:1) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at android.os.AsyncTask.finish(AsyncTask.java:417) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at android.os.AsyncTask.access$300(AsyncTask.java:127) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at android.os.Handler.dispatchMessage(Handler.java:99) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at android.os.Looper.loop(Looper.java:123) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at android.app.ActivityThread.main(ActivityThread.java:4627) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at java.lang.reflect.Method.invokeNative(Native Method) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at java.lang.reflect.Method.invoke(Method.java:521) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
08-16 08:15:34.032: E/AndroidRuntime(21957): at dalvik.system.NativeStart.main(Native Method) 

Я не добавляя сюда AsyncTask код, как они правильно работают без нажатия кнопки назад или выхода из приложения. Я звоню всем AsyncTask, как новый GetTaskDone().execute(parameter), и есть onPostExecute в каждом AsycTask.

Как я могу избежать сбоя приложения?

Edit:

Теперь я имею в виду, что, возможно, проблема не в AsyncTask. Потому что мой другой AsyncTask работает независимо от обратного вызова/выхода.

Это проблематично AsyncTask:

защищенный класс GetProblemListTask расширяет AsyncTask {

@Override 
protected Void doInBackground(String... params) { 
    InputStreamReader isr = null; 
    if (hasConnection) { 
     Date date = new Date(); 
     long savedTime = prefs.getLong(CommonUtils.LAST_SAVED, 
       date.getTime()); 
     long now = date.getTime(); 
     if (now - savedTime > fiveDays 
       || (now - savedTime <= fiveDays && prefs.getBoolean(
         CommonUtils.problemListisCached, false) == false)) { 
      if (CommonUtils.isDebuggable) { 
       Log.d("updating", "need to update!"); 
      } 
      prefs.edit() 
        .putBoolean(CommonUtils.problemListisCached, false) 
        .commit(); 
      isr = new JSONDownloader().getJSONStringFromUrl(params[0]); 
      BufferedReader br = new BufferedReader(isr, bufferSize); 
      StringBuilder sb = new StringBuilder(); 
      String line = null; 
      try { 
       while ((line = br.readLine()) != null) { 
        sb.append(line + "\n"); 
       } 
      } catch (IOException e) { 
       Log.d("problem", "in file writting"); 
      } 
      writeToFile(sb.toString(), CommonUtils.FILE_PROBLEM_LIST); 
      prefs.edit() 
        .putBoolean(CommonUtils.problemListisCached, true) 
        .commit(); 
      try { 
       isr.close(); 
      } catch (IOException e) { 
       if (CommonUtils.isDebuggable) { 
        Log.d("isr", e.toString()); 
       } 
      } 
      try { 
       br.close(); 
      } catch (IOException e) { 
       if (CommonUtils.isDebuggable) { 
        Log.d("br", e.toString()); 
       } 
      } 
      prefs.edit().putLong(CommonUtils.LAST_SAVED, now).commit(); 
     } else { 
      if (CommonUtils.isDebuggable) { 
       Log.d("old_copy", "Old copy is rendering"); 
      } 
      try { 
       isr = new InputStreamReader(
         openFileInput(CommonUtils.FILE_PROBLEM_LIST)); 
      } catch (FileNotFoundException e) { 
       Log.d("file_not_found", "File is missing!"); 
      } 
     } 
    } else { 
     try { 
      isr = new InputStreamReader(
        openFileInput(CommonUtils.FILE_PROBLEM_LIST)); 
     } catch (FileNotFoundException e) { 
      Log.d("file_not_found", "File is missing!"); 
     } 
    } 
    if (CommonUtils.isDebuggable) { 
     Log.d("start", "mapping start"); 
    } 
    try { 
     isr = new InputStreamReader(
       openFileInput(CommonUtils.FILE_PROBLEM_LIST)); 
    } catch (FileNotFoundException e1) { 

    } 
    JsonReader reader = new JsonReader(isr); 
    try { 
     reader.beginArray(); 
     while (reader.hasNext()) { 
      reader.beginArray(); 
      problems.put(
        reader.nextInt(), 
        new Problems(reader.nextString(), reader 
          .nextString(), reader.nextInt())); 
      while (reader.hasNext()) 
       reader.skipValue(); 
      reader.endArray(); 
     } 
     reader.endArray(); 
     reader.close(); 
    } catch (IOException e) { 
     if (CommonUtils.isDebuggable) { 
      Log.d("problems", "hashmaping problem"); 
     } 
    } 
    return null; 
} 

@Override 
protected void onPostExecute(Void result) { 
    getSupportActionBar().setHomeButtonEnabled(true); 
    getSupportActionBar().setDisplayHomeAsUpEnabled(true); 
// this is selecItem() function. It's task is to add a fragment to the activity. 
    selectItem(0); 
    if (CommonUtils.isDebuggable) { 
     Log.d("successful", "eventually survived!"); 
    } 
} 

}

+1

Нам нужно увидеть код «AsyncTask», который поможет вам. У этого есть что-то, чтобы сделать метод 'selectItem' в' MainActivity'. это все, что я могу вам рассказать. –

+0

Ницца поймать сэр. Я могу понять. Я отредактировал свой вопрос и добавлю код 'AsyncTask'. Посмотрите! –

+0

Является ли selectItem размещением пользовательского интерфейса? Если так, то это не нужно. 'onPostExecute' запускается в потоке пользовательского интерфейса. Трассировка стека говорит, что строка 434 в MainActivity является источником проблемы.Посмотрите на эту линию, что вызывает крушение. –

ответ

2

AsyncTask в onPreExecute и onPostExecute запустить в потоке пользовательского интерфейса. Я предполагаю, что вы не сохраняете экземпляр AsyncTask в настоящее время и вызываете его отмену в onDestroy фрагмента/активности.

Либо добавьте это, либо добавьте логический флаг, указывающий, видно ли приложение или нет (API 17 представлен Activity.isDestroyed(), если вы используете уровень API> = 17, просто используйте это).

Примечание: Если добавить вызов отменить AsyncTask, вам все равно нужно вызвать что-то вдоль линий:

if(isCancelled()) { return; } 

в начале вашего onPostExecute.

Edit: Более полный пример isCancelled() метода:

В вашей деятельности:

protected void onDestroy() { 
    super.onDestroy(); 

    if(task != null && task.getStatus() != AsyncTask.Status.FINISHED) { 
     task.cancel(true); 
    } 
} 

, а затем назначить задание переменной класса шириной, вы можете просто добавить task = к линии, что это делая new AsyncTask().execute();, и он будет работать точно так же, как сейчас.

В соответствии с документацией для AsyncTask.cancel(), это фактически гарантирует, что ваш onPostExecute никогда не будет вызван, поэтому вам даже не нужно делать проверку isCancelled(), как я уже говорил ранее.

+1

Спасибо за ваш ответ! Я использую ниже уровня API 17 и, согласно вашему совету, добавляю 'if (isCancelled()) {return; } 'в начале каждого' onPostExecute'. Но это не работает! Приложение рушится и показывает почти тот же самый логарифм, который я предоставил. Также я не рассматривал экземпляр, я назвал их как новый 'AsyncTaskName(). Execute()' –

+0

@typedf, используя isCancelled(), ничего не сделает, если вы фактически не сохраните экземпляр asynctask и не отмените вызов Это. вызывающий .execute() фактически возвращает AsyncTask для удобства доступа, поэтому вы можете выполнить задачу GetProblemListTask = GetProblemListTask(). execute(); 'затем переопределить' onDestroy() 'в вашей активности/фрагменте и вызвать' task.cancel (true) ', если задача все еще запущена, как возвращено из' task.getStatus() ' –

+0

@typedef. Я изменил свой ответ, чтобы дать больше контекста тому, что я имел в виду. –