【问题标题】:Calling the same AsyncTask repeatedly重复调用同一个 AsyncTask
【发布时间】:2017-01-22 18:57:57
【问题描述】:

这就是我正在尝试做的事情:定期检查某个网站,解析 XML 并在满足某些条件时使手机振动。我有一个 AsyncTask,我在其中声明了一个 XmlPullParser - 我检查了 XML 标签,一旦找到我感兴趣的标签,它就会检查该值并让手机振动,如果该值在我想要的范围内是;但是,当我尝试重复运行它时,我遇到了一个 catch-22。

我正在查看 this StackOverflow post 并采用了该实现,但发生了以下情况:

onStart 我有一个startTimer 函数,看起来像这样:

private synchronized void startTimer(final Context context){
    timer = new Timer();
    TimerTask task = new TimerTask(){
        @Override
        public void run(){
            executing.set(true);
            functionThatExecutesAsyncTask();
        }
    };
    timer.schedule(task, 01, updateFrequency);
}

我遇到的第一个问题是每次我切换到应用程序(或翻转屏幕)时都会创建一个新计时器,每个计时器都会通过 updateFrequency 执行 AsyncTask。 Threads 调试窗口中还有五个 AsyncTasks(都列为“WAITING”),好像每个计时器都创建了一个新任务而不是同一个;令人惊讶的是,虽然我有超过 5 个计时器,但出于某种原因,我从来没有超过 5 个任务。为了解决多个定时器的问题,我决定覆盖onStop 并去掉现有的定时器(如果我正在翻转手机并希望新的定时器来调用任务,这也会有所帮助):

@Override
public void onStop() {
    super.onStop();
    if(timer != null) {
        timer.cancel();
        timer.purge();
        timer = null;
    }
    // ATTENTION: This was auto-generated to implement the App Indexing API.
    // See https://g.co/AppIndexing/AndroidStudio for more information.
    AppIndex.AppIndexApi.end(client, getIndexApiAction());
    client.disconnect();
}

这里的问题很明显:即使没有创建额外的计时器,我也没有任何东西可以让手机以定义的间隔振动,因为当应用停止时每个计时器都会被破坏。它也没有解决创建多个 AsyncTask 的问题。

以下是问题:

  • 在另一篇 StackOverflow 帖子中,有人建议不要使用 AsyncTask 重复执行任务,而是使用线程,但这只是一个建议,而搜索“重复调用 AsyncTask”会产生大量结果。 AsyncTask 不适合在这里使用吗?

  • 我怎样才能每次只调用一个 AsyncTask,而不是五个?为什么要创建五个?

  • 如何避免具有无限个计时器或根本没有计时器的 catch-22?即使屏幕关闭并且手机在我的口袋深处,我也绝对希望应用程序继续更新。

【问题讨论】:

  • 您只在onStart 中调用startTimer
  • @Dummy - 是的。我在把它放在onStartonCreate 之间有点矛盾,但决定用onStart
  • onCreate 仅在您的应用程序开始“新鲜”时调用,而不是在您恢复应用程序时调用,onResume 无论如何总是调用,@987654337 @ 在停止后导航回应用程序时调用(它在后台有一段时间但仍然存在)
  • @Dummy 对,但我认为 onCreate 就足够了——定时器只需要在应用程序“新鲜”时创建——之后,同一个定时器可以继续调用任务。
  • 你应该改用AsyncTaskLoader

标签: android android-asynctask


【解决方案1】:

如果timer 为空,我们知道它还不存在,所以可以安全地创建一个新的。 timer 在这些情况下为空:

  • 您的应用开始“新鲜”
  • 您的应用已被 android 销毁,因为它闲置了一段时间(在后台)。

if (timer == null) { startTimer(this); }

【讨论】:

  • 根据您的 cmets,检查 SharedPreferences 中是否有任何 isTimerCreated 将在 onCreate 而不是 onStart 中完成,对吗?另外,这会解决创建多个 AsyncTask 的问题吗?
  • 其实我的回答并不完美,因为如果你的应用程序被销毁,这意味着你的计时器对象也会被销毁,但是isTimerCreated 仍然是正确的,所以在这种情况下,那不会'不工作。检查我的新编辑。取决于您的用例,我们可以在任何地方调用它,因为您已经有了这个守卫if (timer == null),只要在创建Timer 后您的应用没有被销毁,它就不会多次调用startTimer
  • 所以如果我理解正确的话:在三种情况下它可以被破坏 - 当我旋转手机时,当我关闭应用程序时或当它在后台运行很长时间时。对吗?
  • @RockOnRockOut 正确
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-20
  • 2020-05-05
  • 2012-03-16
相关资源
最近更新 更多