В чем разница между заданием + контекстом пользовательского интерфейса и использованием parent = job?

Руководство UI Coroutines Guide содержит раздел о том, как управлять жизненным циклом сопрограмм пользовательского интерфейса. В нем объясняется, что мы должны создать экземпляр Job верхнего уровня и передать контекст составной сопрограммы contextJob + UI всем запускаемым сопрограммам:

launch(contextJob + UI, block = block)

При реализации этого шаблона в моем проекте для меня стало естественным использовать вместо этого contextJob в качестве родителя:

launch(UI, parent = contextJob, block = block)

Я еще не проверял разницу в поведении, но меня интересует семантическая разница между этими двумя вариантами. На мой взгляд, они очень похожи, но я бы предпочел использовать parent = contextJob, поскольку это более очевидно, что он делает. В частности, я отмечаю, что parent может быть null, но если я использую +, мне, вероятно, придется использовать NonCancellable в качестве нулевого объекта.

Есть ли что-нибудь неправильное в использовании contextJob в качестве parent аргумента для launch или actor?


person Marko Topolnik    schedule 25.06.2018    source источник


Ответы (1)


Смысловой разницы нет и не будет.

Возможность использования оператора + естественным образом связана с coroutineContext оборудованием: Job - это элемент контекста, поэтому он может быть добавлен к контексту.

Но написание launch(UI + job) кажется неестественным, потому что намерение неясно. Что вообще означает объединение диспетчера пользовательского интерфейса и некоторой работы? Чтобы сделать такой шаблон читаемым, был добавлен параметр parent, launch(UI, parent = job) - более естественный способ раскрыть намерение запустить задание в качестве дочернего элемента данного родителя. Под капотом он по-прежнему объединяет контекст и родительский элемент, но теперь API выглядит лучше для пользователей.

Обратите внимание, что такой же подход можно использовать для других элементов библиотеки, например. для CoroutineExceptionHandler, но это компромисс: либо у вас есть метод с дюжиной параметров по умолчанию, либо вы жертвуете удобочитаемостью и пишете launch(ctx + myExceptionHandler), поэтому было решено ввести только параметр parent как наиболее распространенный.

person qwwdfsad    schedule 27.06.2018
comment
Спасибо, этот ответ точный! Однако в нем отсутствуют какие-либо авторитетные ссылки, и ваш текущий профиль не показывает, являетесь ли вы человеком, который может утверждать такой авторитетный ответ. Вы член команды JetBrains, работающей над этим? - person Marko Topolnik; 27.06.2018
comment
Да, я являюсь членом команды JetBrains, которая также работает над kotlinx.coroutines: github.com/qwwdfsad - person qwwdfsad; 27.06.2018