Я тестирую AsyncTask
, который onPostExecute
вызывает setValue
экземпляра LiveData
. Поскольку я вызываю setValue
из onPostExecute
, никаких проблем, связанных с вызовом, выполняемым потоком пользовательского интерфейса, не ожидалось.
Тем не менее, выполнив это в модульном тесте Robolectric, я получил: java.lang.IllegalStateException: Cannot invoke setValue on a background thread
Чтобы заставить этот модульный тест ждать завершения фоновых и передних задач, я использую инструмент awaitility следующим образом:
var cf = new CompletableFuture<T>();
livedata.observe(ctrl.get(), it -> cf.complete(it));
// ... perform the AsyncTask that will update livedata in onPostExecute
await().until(() -> {
flushBackgroundThreadScheduler()
flushForegroundThreadScheduler()
cf.isDone
});
Это вызов IllegalStateException: Cannot invoke setValue on a background thread
на flushForegroundThreadScheduler()
!! !!
Почему я получаю это исключение? И как я могу выполнить onPostExecute
как в потоке пользовательского интерфейса?
ОБНОВЛЕНИЕ
Журналирование потоков кажется, что и flushBackgroundThreadScheduler()
, и flushForegroundThreadScheduler()
выполняется синхронно на линии. Я могу наблюдать:
LiveData created on thread 763324286
Background thread 1519527121
LiveData updated on thread 1519527121
Поскольку лямбда, переданная в await.until
, работает в другом потоке, то и flushBackgroundThreadScheduler()
и flushForegroundThreadScheduler()
выполняются в этом потоке 1519527121.
Таким образом,Я могу решить мою проблему с помощью следующего обходного пути, запущенного в тестовом потоке, соответствующем UI-потоку. Тем не менее, мне нужно это Thread.sleep()
, чтобы добиться успеха, и мне это не нравится.
Thread.sleep(1000)
flushBackgroundThreadScheduler()
flushForegroundThreadScheduler()
cf.isDone