从后台恢复时,从计时器异步执行任务会冻结UI

时间:2016-01-06 10:21:49

标签: android scala android-asynctask

我正在开发的应用程序显示本地电车的时间表。数据从网站获取,应每30秒刷新一次。为了在后台执行fetch,我以更适合scala的方式重新实现了AsyncTask。

摘录自class RichFuture[T](future: Future[U]),通过隐式转换来丰富Future

def mapUI[U](func: (T) ⇒ U)(implicit activity: Activity, ec: ExecutionContext): Future[U] = {
  val promise = Promise[U]
  future andThen {
    case Success(value) ⇒
      activity.runOnUiThread(new Runnable {
        override def run(): Unit = {
          try {
            promise.success(func(value))
          } catch {
            case t: Throwable ⇒ promise.failure(t)
          }
        }
      })
    case Failure(fail) ⇒
      promise.failure(fail)
  }
  promise.future
}

这基本上取代了AsyncTask which does not work in scala。全班可以在github看到。我不认为这是相关的。

获取函数函数如下所示:

def fetchSchedule(): Unit = {
  implicit val ec: ExecutionContext = ExecutionContext.fromExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
  Schedule.fetch(station) mapUI { schedules ⇒
    Log.w("Jenastop", "Schedules are fetched")
    /* Display results in UI */
  } recoverUI {
    case t: Throwable ⇒
      /* Display error in UI */
  }
}

调用fetchSchedule的地方是:

protected override def onResume(): Unit = {
  super.onResume()

  Log.w("Jenastop", "Resume started")

  // Setup timer that refreshes the data every 30
  // seconds.
  timer = new Timer
  timer.scheduleAtFixedRate(new TimerTask {
    override def run(): Unit = fetchSchedule()
  }, 0, 30000)

  Log.w("Jenastop", "Resume finished")
}

现在的问题是:每当我将Activity放在后台并尝试恢复它时,它会冻结,直到获取计划。当我第一次开始活动时,这种情况不会发生,但只有当我尝试从后台恢复时才会发生。

从后台恢复时的日志输出是:

01-06 11:19:06.694  5280  5280 W Jenastop: Resume started
01-06 11:19:06.694  5280  5280 W Jenastop: Resume finished
01-06 11:19:07.974  5280  5280 I Choreographer: Skipped 71 frames!  The application may be doing too much work on its main thread.
01-06 11:19:07.974  5280  5280 W Jenastop: Schedules are fetched
/* UI unfreezes */

在某种程度上,UI似乎会阻塞,直到THREAD_POOL_EXECUTOR中的任务完成。我怎么能绕过这个?

1 个答案:

答案 0 :(得分:0)

错误与模拟器有某种关联。在真实设备上运行代码时,根本不会发生延迟。

在模拟器上,似乎活动仅在线程池耗尽时才会恢复。我通过向网络连接添加恒定延迟来测试它。

如果有人对这里发生的事情有更好的答案,我会很乐意接受它,但由于这只是调试过程中的一个问题,我没有动力去研究它