【问题标题】:AsyncTask gets out of step when hitting Home button over and over again一遍又一遍地点击主页按钮时,AsyncTask 会失步
【发布时间】:2012-11-16 21:19:18
【问题描述】:

我有一个执行大量 JSON 计算的 AsyncTask。

public class InitializationTask extends AsyncTask<Void, Void, InitializationResult> {
    private ProcessController processController = new ProcessController();
    private ProgressDialog progressDialog;
    private MainActivity mainActivity;

    public InitializationTask(MainActivity mainActivity) {
        this.mainActivity = mainActivity;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

        progressDialog = new ProgressDialog(mainActivity);
        progressDialog.setMessage("Die Daten werden aufbereitet.\nBitte warten...");
        progressDialog.setIndeterminate(true); //means that the "loading amount" is not measured.
        progressDialog.setCancelable(false);
        progressDialog.show();
    };

    @Override
    protected InitializationResult doInBackground(Void... params) {
        return processController.initializeData();
    }

    @Override
    protected void onPostExecute(InitializationResult result) {
        super.onPostExecute(result);

        progressDialog.dismiss();

        if (result.isValid())  {
            mainActivity.finalizeSetup();
        }
        else  {
            AlertDialog.Builder dialog = new AlertDialog.Builder(mainActivity);
            dialog.setTitle("Initialisierungsfehler");
            dialog.setMessage(result.getReason());
            dialog.setPositiveButton("Ok",
                    new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.cancel();

                            mainActivity.finish();
                        }
                    });

            dialog.show();
        }
    }
}

processController.initializeData() 运行大约 20 秒。这一切都有效。它甚至可以在我安装应用程序并在应用程序初始化时按主页按钮时工作。 AsyncTask 在后台工作。当我在 AsyncTask 完成后再次从 Android 设备重新启动应用程序时,应用程序仍然可以工作。
但是应用程序无法处理这种用例:当我部署应用程序时(或在没有数据初始化时启动它),因此初始化数据确实需要大约 20 秒,而当我在初始化时回家关闭应用程序时(AsyncTask ) 在后台运行并再次启动应用程序,它会导致 RuntimExceptions 等意外行为。设备似乎要加载应用程序两次,但都无法成功启动。如何处理?
我考虑过检查 MainActivity 中是否有正在运行的 AsyncTask 以避免再次启动它:

private InitializationTask initializationTask = new InitializationTask(this);

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    if (!AsyncTask.Status.RUNNING.equals(initializationTask.getStatus()))  {
        initializationTask.execute((Void[])null);
    }

    initializeMap();
}

不幸的是,这并没有起到任何作用。此外,我不确定这样的用例是否可行,因为当我两次启动同一个应用程序时,它们无法“共享”AsyncTask。我应该以某种方式避免两次启动应用程序吗?我不确定我有什么选择?有什么想法吗?

【问题讨论】:

  • 还要确保你没有在 onPause 之后让任务继续运行。
  • @Tom Dignan 好的,我会记住的。

标签: android concurrency android-asynctask runtimeexception


【解决方案1】:

我通常会更直言不讳。当我不使用它时,我将我的AsyncTask 引用设置为 null。当onClick 触发时,我检查它是否不为空,这意味着我启动了它。如果它为空,我会在那里创建并执行一个新的AsyncTask。它速度很快,而且足够干净。这种方法的一个好处是AsyncTask 无论如何只能执行一次,所以它非常适合。在onPostExecute 的末尾,如果您打算留在同一个Activity,可以再次将引用设置回null

在完善 AsyncTask 流程时,请确保它也是 survives orientation changes

【讨论】:

  • 你的意思是onCreate而不是onClick?
  • 我认为我的问题有所不同。由于 JSON 框架导致的 NullPointerExceptions 或 Exception 导致任务调用的方法步调不一致。似乎这些方法仍然以某种方式执行,但由于任务取消而导致数据损坏。
  • ...顺便说一句:在您的链接的此代码示例中使用的 getLastNonConfigurationInstance() 已弃用。
  • @Bevor -- 当然,我完全清楚这一点。这并没有改变这样一个事实,即在野外存在仍然使用这种方法的代码。无论如何,您都需要注意方向的变化。 -- 如果您在 Activity 中声明 AsyncTask 而不是在 Fragment 中声明,那么在方向更改上保持它的最佳方法是使用上述方法中阐明的方法。您可以指出该方法已被弃用,但现在您编写代码的方式依赖于弃用的方法才能正常工作(或使用服务,这是一个不同的对话)
  • “以依赖于弃用方法的方式编写代码”到底是什么意思。我的代码到底弃用了什么?
【解决方案2】:

我找到了解决方案:这实际上不是 AsyncTask 问题。问题是我在 processController.initializeData() 中调用的 JSONParser 解析方法(完成大部分工作)没有同步。

【讨论】:

  • processController.initializeData() 是否在单独的线程上运行?您不需要这样做,因为已经在线程池中为您调用了 doInBackground。 onPreExecute、doInBackground 和 onPostExecute 总是一个接一个地执行,doInBackground 在单独的线程上执行,另外两个在主/UI 线程上。
  • @Tom Dignan 不,processController.initializeData() 不是一个单独的线程。问题是 JSONSimple.parse 不同步,这就是为什么我必须同步我的 parse 方法,它使用这个方法。主要问题是解析大约需要 20 秒,当我启动一个新的 AsyncTask 时,之前的解析还没有完成,一个不同步的解析方法无法处理这个问题。当我同步它时,它不再稳定了。 (而且我也使用了您的链接代码,也许两者的结合是正确的解决方案)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
  • 1970-01-01
  • 1970-01-01
  • 2019-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多