简体   繁体   中英

Executing task asynchronously from a timer freezes UI when resuming from background

The app i am developing is displaying schedules for local trams. The data is fetched from a website and should be refreshed every 30 seconds. For executing the fetch in background i reimplemented AsyncTask in a way more suited for scala.

Excerpt from class RichFuture[T](future: Future[U]) which is enriching Future via an implicit conversion:

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
}

This essentially replaces AsyncTask which does not work in scala . The full class can be seen at github . I do not think it's relevant though.

The fetch function functions looks like this:

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 */
  }
}

The place where fetchSchedule is called is this:

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")
}

Now the problem: Whenever i put the Activity in the background and try to resume it, it freezes until the schedules are fetched. This does not happen when i first start the activity but only when i try to resume it from background.

Log output when resuming from background is this:

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 */

Somehow the UI seems to block until the tasks in THREAD_POOL_EXECUTOR are finished. How can i circumvent this?

The error is somehow related to the emulator. When running the code on a real device the delay is not happening at all.

On the emulator however it seems like the activity only resumes when the thread pool is depleted. I tested that by adding a constant delay to the network connection.

If someone has a better answer to what exactly is happening here I'll be glad to accept it but as it is only an issue during debugging I am not motivated to research it any further

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM