Котлин Corountines: Примечание: время окончания превышает эпоху: - PullRequest
0 голосов
/ 12 октября 2018

Объединение runBlocking и withContext, кажется, отправляет сообщение Note: end time exceeds epoch:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        runBlocking {
            withContext(DefaultDispatcher) {
                null
            }
        }
    }
}

Я использую много сопрограмм, как это, и logcat спам, есть идеи, чтобы избежать этого?Другой способ сделать это, например:

var projects: List<ProjectEntity>? = runBlocking {
    withContext(DefaultDispatcher) {
        //Get the ProjectEntity list
    }
}
projects?.let {
    onResult(projects)
}

РЕДАКТИРОВАТЬ

Я пробую что-то на основе ваших комментариев (спасибо), но не могу получитьрезультат, подобный моему примеру выше:

Log.d("Coroutines", "getMostRecent start")
var localeProject: ProjectEntity? = null
launch {
    withContext(CommonPool) {
        Log.d("Coroutines", "getRecentLocaleProject")
        localeProject = getRecentLocaleProject()
    }
}
Log.d("Coroutines", "check localeProject")
if (localeProject != null) {
    //Show UI
}

В Logcat:

D/Coroutines: getMostRecent start
D/Coroutines: check localeProject
D/Coroutines: getRecentLocaleProject

Я хочу разделить асинхронные и синхронизирующие вещи, нет такого способа?Я действительно хочу по возможности избегать всех обратных вызовов в моих репозиториях.

Ответы [ 2 ]

0 голосов
/ 15 октября 2018
var localeProject: ProjectEntity? = null
launch {
    withContext(CommonPool) {
        localeProject = getRecentLocaleProject()
    }
}
if (localeProject != null) {
    //Show UI
}

Я хочу разделить асинхронный и синхронизирующий материал, нет такого способа?

Когда вы launch сопрограмма, семантически это похоже на вас start edТема.Интуиция говорит вам, что вы не можете ожидать localeProject != null только после того, как запустили поток, который его устанавливает, и это верно и для сопрограммы.Это даже сильнее: вы гарантированно никогда не увидите localeProject != null, потому что launch только добавляет новое событие в цикл событий.Пока ваш текущий метод не завершится, это событие не будет обработано.

Так что вы можете забыть о val элементах верхнего уровня, инициализированных из асинхронного кода.Даже lateinit var не может работать, потому что у вас нет гарантии, что вы увидите, что он уже инициализирован.Вы должны работать с самым свободным видом: nullable var s.

0 голосов
/ 12 октября 2018

Комментарий Markos верен, вы не должны блокировать поток пользовательского интерфейса.

Вы должны использовать launch или async и использовать withContext, чтобы переключиться обратно на поток пользовательского интерфейса.

Здесь вы найдете несколько примеров: https://github.com/Kotlin/kotlinx.coroutines/blob/master/ui/coroutines-guide-ui.md#structured-concurrency-lifecycle-and-coroutine-parent-child-hierarchy

class MainActivity : ScopedAppActivity() {

    fun asyncShowData() = launch { // Is invoked in UI context with Activity's job as a parent
       // actual implementation
    }

    suspend fun showIOData() {
        val deferred = async(Dispatchers.IO) {
        // impl      
        }
        withContext(Dispatchers.Main) {
          val data = deferred.await()
          // Show data in UI
        }
    }
}

Имейте в виду, что в примере используется новый сопрограммный API (> 0.26.0), который переименован в Диспетчеры.Так что Dispatchers.Main соответствует UI в более старых версиях.

...