2016-01-06 49 views
1

我正在開發的應用程序顯示本地電車的時間表。數據從網站獲取,應該每30秒刷新一次。爲了在後臺執行提取操作,我以更適合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") 
} 

現在的問題:每當我把活動的背景和嘗試恢復它,它凍結,直到取得時間表。當我第一次啓動活動時,這種情況不會發生,但只有當我嘗試從後臺恢復時纔會發生。從背景中恢復時

日誌輸出是這樣的:

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

一個小細節。而不是'try {promise.successful(...)} catch ...}',你應該簡單地運行'promise.complete(Try(func(value)))'。 –

+0

不是Android專家。所以'Schedule.fetch'運行一個未來,對吧?是否有一個原因,你必須使用'AsyncTask.THREAD_POOL_EXECUTOR'?根據我的經驗,您可以通過自定義池輕鬆阻止期貨。如果您使用默認執行上下文,則可以在將來需要避免此類情況的機構中使用'blocking {}'。 –

+0

因爲您在'Schedule.fetch'內使用的Jsoup可能是阻塞的。使用異步http庫可能會更好。再一次,我在這裏幾乎沒有想法,但也許[這個博客](http://blog.ashwanik.in/2015/04/html-parsing-using-jsoup-and-volley-in-android.html)有助於做所以。 –

回答

0

該錯誤與模擬器相關。在真實設備上運行代碼時,延遲根本不會發生。

但是,在仿真器上,似乎活動僅在線程池耗盡時纔會恢復。我通過給網絡連接添加一個不變的延遲來測試它。

如果有人有更好的答案,究竟是發生在這裏我很樂意接受它,但因爲它是在調試過程中只有一個問題,我沒有動力去研究它的任何進一步