1

AsyncTask在我的一些FragmentActivity这些工作中使用得很好。但问题是当我在Asynchronous任务执行时按下后退按钮或退出应用程序时,应用程序崩溃。这是我的日志猫:

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.

如何避免应用程序崩溃?

编辑:

现在我在想,问题可能不在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!");
    }
}

}

4

1 回答 1

3

AsyncTaskonPreExecuteonPostExecute在 UI 线程上运行。我假设您当前没有保留 AsyncTask 的实例并在您的片段/活动的onDestroy.

要么添加它,要么添加一个布尔标志,说明应用程序是否可见(API 17 引入Activity.isDestroyed(),如果您使用 API 级别 >= 17,只需使用它)。

注意:如果你添加一个调用来取消 AsyncTask,你仍然需要调用一些类似的东西:

if(isCancelled()) { return; }

在你的开头onPostExecute

编辑:该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()像我之前所说的那样进行检查。

于 2013-08-16T01:46:28.523 回答