我正在开发的应用程序显示本地电车的时间表。数据从网站获取,应每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中的任务完成。我怎么能绕过这个?
答案 0 :(得分:0)
错误与模拟器有某种关联。在真实设备上运行代码时,根本不会发生延迟。
在模拟器上,似乎活动仅在线程池耗尽时才会恢复。我通过向网络连接添加恒定延迟来测试它。
如果有人对这里发生的事情有更好的答案,我会很乐意接受它,但由于这只是调试过程中的一个问题,我没有动力去研究它