{"id":315173,"date":"2020-12-19T21:01:09","date_gmt":"2020-12-19T21:01:09","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=315173"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=315173","title":{"rendered":"Kotlin Multiplatform. \u0420\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441 \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435. \u0427.2"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\">\u0414\u043e\u0431\u0440\u043e\u0433\u043e \u0432\u0441\u0435\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0443\u0442\u043e\u043a! \u0421 \u0432\u0430\u043c\u0438 \u044f, \u0410\u043d\u043d\u0430 \u0416\u0430\u0440\u043a\u043e\u0432\u0430, \u0432\u0435\u0434\u0443\u0449\u0438\u0439 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u00abUsetech\u00bb.<br \/>  <a href=\"https:\/\/habr.com\/ru\/post\/533864\/\">\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u0430 \u043f\u0440\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 Kotlin Multiplatform. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0440\u0430\u0441\u0448\u0430\u0440\u0438\u0432\u0430\u0435\u043c\u044b\u043c \u043e\u0431\u0449\u0438\u043c \u043a\u043e\u0434\u043e\u043c, \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u044f \u0432\u0441\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043f\u043e\u0442\u043e\u043a\u0430\u043c\u0438 \u0432 \u043e\u0431\u0449\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443. <br \/>  \u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0433\u043b\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 Ktor, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u0437\u044f\u043b\u0430 \u043d\u0430 \u0441\u0435\u0431\u044f \u0432\u0441\u044e \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u0438 \u0432 \u0441\u0435\u0442\u0435\u0432\u043e\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0435. \u042d\u0442\u043e \u0438\u0437\u0431\u0430\u0432\u0438\u043b\u043e \u043d\u0430\u0441 \u043e\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c DispatchQueue \u043d\u0430 iOS \u0432 \u0442\u043e\u043c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043d\u043e \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u043d\u0430\u043c \u0431\u044b \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0442\u0432\u0435\u0442\u0430. \u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 Android \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 MainScope \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 suspended \u0444\u0443\u043d\u043a\u0446\u0438\u0438. <br \/>  <a name=\"habracut\"><\/a><br \/>  \u0418\u0442\u0430\u043a, \u0435\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0434\u0438\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c\u044e \u0432 \u043e\u0431\u0449\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u0442\u043e \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c scope \u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u044b, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f. <br \/>  \u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0430\u0448\u0435\u0433\u043e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e\u0433\u043e \u043f\u043e\u0441\u0440\u0435\u0434\u043d\u0438\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0432 \u0441\u0432\u043e\u0435\u043c scope, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c\u043e\u043c \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u044b:  <\/p>\n<pre><code class=\"kotlin\">class PresenterCoroutineScope(context: CoroutineContext) : CoroutineScope {     private var onViewDetachJob = Job()     override val coroutineContext: CoroutineContext = context + onViewDetachJob      fun viewDetached() {         onViewDetachJob.cancel()     } }  \/\/\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u043f\u043e\u0441\u0440\u0435\u0434\u043d\u0438\u043a\u0430 abstract class BasePresenter(private val coroutineContext: CoroutineContext) {     protected var view: T? = null     protected lateinit var scope: PresenterCoroutineScope      fun attachView(view: T) {         scope = PresenterCoroutineScope(coroutineContext)         this.view = view         onViewAttached(view)     } } <\/code><\/pre>\n<p>  \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0438\u0441 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 \u043f\u043e\u0441\u0440\u0435\u0434\u043d\u0438\u043a\u0430 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u043d\u0430\u0448\u0435\u043c\u0443 UI:  <\/p>\n<pre><code class=\"kotlin\">class MoviesPresenter:BasePresenter(defaultDispatcher){     var view: IMoviesListView? = null      fun loadData() {         \/\/\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0432 \u0441\u043a\u043e\u0443\u043f\u0435         scope.launch {             service.getMoviesList{                 val result = it                 if (result.errorResponse == null) {                     data = arrayListOf()                     data.addAll(result.content?.articles ?: arrayListOf())                     withContext(uiDispatcher){                     view?.setupItems(data)                    }                 }             }         }  \/\/IMoviesListView - \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\/\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0443\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c UIViewController \u0438 Activity.  interface IMoviesListView  {   fun setupItems(items: List&lt;MovieItem&gt;) } class MoviesVC: UIViewController, IMoviesListView { private lazy var presenter: IMoviesPresenter? = {        let presenter = MoviesPresenter()         presenter.attachView(view: self)         return presenter     }()      override func viewWillAppear(_ animated: Bool) {         super.viewWillAppear(animated)         presenter?.attachView(view: self)         self.loadMovies()     }      func loadMovies() {         self.presenter?.loadMovies()     }     func setupItems(items: List&lt;MovieItem&gt;){} \/\/....  class MainActivity : AppCompatActivity(), IMoviesListView {     val presenter: IMoviesPresenter = MoviesPresenter()      override fun onResume() {         super.onResume()         presenter.attachView(this)         presenter.loadMovies()     }     fun  setupItems(items: List&lt;MovieItem&gt;){} \/\/... <\/code><\/pre>\n<p>  \u0427\u0442\u043e\u0431\u044b \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c scope \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u044b, \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u0434\u0430\u0442\u044c \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440 \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u044b.<br \/>   \u042d\u0442\u043e \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e expect\/actual.  <\/p>\n<pre><code class=\"kotlin\">expect val defaultDispatcher: CoroutineContext  expect val uiDispatcher: CoroutineContext <\/code><\/pre>\n<p>  uiDispatcher \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 \u0432 \u043f\u043e\u0442\u043e\u043a\u0435 UI. defaultDispatcher \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u043d\u0435 UI \u043f\u043e\u0442\u043e\u043a\u0430.<br \/>  \u041f\u0440\u043e\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0432 androidMain, \u0442.\u043a \u0432 Kotlin JVM \u0435\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u043e\u0432 \u043a\u043e\u0440\u0443\u0442\u0438\u043d. \u0414\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u043f\u043e\u0442\u043e\u043a\u0430\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c CoroutineDispatchers Main (UI \u043f\u043e\u0442\u043e\u043a) \u0438 Default (\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0434\u043b\u044f Coroutine):  <\/p>\n<pre><code class=\"kotlin\">actual val uiDispatcher: CoroutineContext     get() = Dispatchers.Main  actual val defaultDispatcher: CoroutineContext     get() = Dispatchers.Default<\/code><\/pre>\n<p>  \u0414\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440 MainDispatcher \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c CoroutineDispatcher \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0430\u0431\u0440\u0438\u043a\u0438 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u043e\u0432 MainDispatcherLoader:<\/p>\n<pre><code class=\"kotlin\">internal object MainDispatcherLoader {      private val FAST_SERVICE_LOADER_ENABLED = systemProp(FAST_SERVICE_LOADER_PROPERTY_NAME, true)      @JvmField     val dispatcher: MainCoroutineDispatcher = loadMainDispatcher()      private fun loadMainDispatcher(): MainCoroutineDispatcher {         return try {             val factories = if (FAST_SERVICE_LOADER_ENABLED) {                 FastServiceLoader.loadMainDispatcherFactory()             } else {                 \/\/ We are explicitly using the                 \/\/ `ServiceLoader.load(MyClass::class.java, MyClass::class.java.classLoader).iterator()`                 \/\/ form of the ServiceLoader call to enable R8 optimization when compiled on Android.                 ServiceLoader.load(                         MainDispatcherFactory::class.java,                         MainDispatcherFactory::class.java.classLoader                 ).iterator().asSequence().toList()             }             @Suppress(&quot;ConstantConditionIf&quot;)             factories.maxBy { it.loadPriority }?.tryCreateDispatcher(factories)                 ?: createMissingDispatcher()         } catch (e: Throwable) {             \/\/ Service loader can throw an exception as well             createMissingDispatcher(e)         }     } } <\/code><\/pre>\n<p>  \u0422\u0430\u043a \u0436\u0435 \u0438 \u0441 Default:  <\/p>\n<pre><code class=\"kotlin\">internal object DefaultScheduler : ExperimentalCoroutineDispatcher() {     val IO: CoroutineDispatcher = LimitingDispatcher(         this,         systemProp(IO_PARALLELISM_PROPERTY_NAME, 64.coerceAtLeast(AVAILABLE_PROCESSORS)),         &quot;Dispatchers.IO&quot;,         TASK_PROBABLY_BLOCKING     )      override fun close() {         throw UnsupportedOperationException(&quot;$DEFAULT_DISPATCHER_NAME cannot be closed&quot;)     }      override fun toString(): String = DEFAULT_DISPATCHER_NAME      @InternalCoroutinesApi     @Suppress(&quot;UNUSED&quot;)     public fun toDebugString(): String = super.toString() } <\/code><\/pre>\n<p>  \u041e\u0434\u043d\u0430\u043a\u043e, \u043d\u0435 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c \u0435\u0441\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u043e\u0432 \u043a\u043e\u0440\u0443\u0442\u0438\u043d. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f iOS, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 Kotlin\/Native, \u0430 \u043d\u0435 \u0441 Kotlin\/JVM. <br \/>  \u0415\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434, \u043a\u0430\u043a \u0432 Android, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043e\u0448\u0438\u0431\u043a\u0443:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/8y\/tn\/uq\/8ytnuqrjvdqhtcui2uuzqd46qzi.png\"><\/p>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c, \u0432 \u0447\u0435\u043c \u0436\u0435 \u0443 \u043d\u0430\u0441 \u0434\u0435\u043b\u043e.<\/p>\n<p>  <a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\/issues\/470\" rel=\"nofollow\">Issue 470<\/a> c GitHub Kotlin Coroutines \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u0447\u0442\u043e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u044b \u0435\u0449\u0435 \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0434\u043b\u044f iOS:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/_k\/si\/hc\/_ksihcqbl4thw514drsubktydls.png\"><\/p>\n<p>  <a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\/issues\/462\" rel=\"nofollow\">Issue 462<\/a>, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 470, \u0442\u043e \u0436\u0435 \u0435\u0449\u0435 \u0432 \u0441\u0442\u0430\u0442\u0443\u0441\u0435 Open:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/oy\/1h\/ru\/oy1hru6ti4spvvscvni_7pttko8.png\"><\/p>\n<p>  \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u043e\u0432 \u0434\u043b\u044f iOS:  <\/p>\n<pre><code class=\"kotlin\">actual val defaultDispatcher: CoroutineContext get() = IODispatcher  actual val uiDispatcher: CoroutineContext get() = MainDispatcher  private object MainDispatcher: CoroutineDispatcher(){     override fun dispatch(context: CoroutineContext, block: Runnable) {         dispatch_async(dispatch_get_main_queue()) {             try {                 block.run()             }catch (err: Throwable) {                 throw err             }         }     } }  private object IODispatcher: CoroutineDispatcher(){     override fun dispatch(context: CoroutineContext, block: Runnable) {         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT.toLong(), 0.toULong())) {             try {                 block.run()             }catch (err: Throwable) {                 throw err             }         }     } <\/code><\/pre>\n<p>  \u041f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0442\u0443 \u0436\u0435 \u0441\u0430\u043c\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443.<br \/>  \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT.toLong(),0.toULong())), \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d \u043d\u0438 \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u043f\u043e\u0442\u043e\u043a\u0443 \u0432 Kotlin\/Native:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/fk\/sb\/rl\/fksbrlxzrbrvxflws6ktwtqwlje.png\"><br \/>  \u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, Kotlin\/Native \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Kotlin\/JVM \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0448\u0430\u0440\u0438\u0442\u044c \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u044b \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u0442\u043e\u043a\u0430\u043c\u0438. \u0410 \u0442\u0430\u043a\u0436\u0435 \u043b\u044e\u0431\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b.<br \/>  \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c MainDispatcher \u0432 \u043e\u0431\u043e\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445:  <\/p>\n<pre><code class=\"kotlin\">actual val ioDispatcher: CoroutineContext get() = MainDispatcher  actual val uiDispatcher: CoroutineContext get() = MainDispatcher   @ThreadLocal private object MainDispatcher: CoroutineDispatcher(){     override fun dispatch(context: CoroutineContext, block: Runnable) {         dispatch_async(dispatch_get_main_queue()) {             try {                 block.run().freeze()             }catch (err: Throwable) {                 throw err             }         }     } <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u043a\u043e\u0434\u0430 \u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u0442\u043e\u043a\u0430\u043c\u0438, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0438\u0445 <a href=\"https:\/\/kotlinlang.org\/api\/latest\/jvm\/stdlib\/kotlin.native.concurrent\/freeze.html\" rel=\"nofollow\">\u0437\u0430\u043c\u043e\u0440\u0430\u0436\u0438\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0434 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439<\/a> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u044b freeze():<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/qd\/yx\/u2\/qdyxu2vs1tf5siy6ih7p88ck0s8.png\"><br \/>  \u041e\u0434\u043d\u0430\u043a\u043e, \u0435\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0437\u0430\u043c\u043e\u0440\u043e\u0437\u0438\u0442\u044c \u0443\u0436\u0435 \u0437\u0430\u043c\u043e\u0440\u043e\u0436\u0435\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u0438\u043d\u0433\u043b\u0442\u043e\u043d\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0447\u0438\u0442\u0430\u044e\u0442\u0441\u044f \u0437\u0430\u043c\u043e\u0440\u043e\u0436\u0435\u043d\u043d\u044b\u043c\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c FreezingException. <br \/>  \u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e, \u043f\u043e\u043c\u0435\u0447\u0430\u0435\u043c \u0441\u0438\u043d\u0433\u043b\u0442\u043e\u043d\u044b \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 @ThreadLocal, \u0430 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 @SharedImmutable:  <\/p>\n<pre><code class=\"kotlin\">\/**  * Marks a top level property with a backing field or an object as thread local.  * The object remains mutable and it is possible to change its state,  * but every thread will have a distinct copy of this object,  * so changes in one thread are not reflected in another.  *  * The annotation has effect only in Kotlin\/Native platform.  *  * PLEASE NOTE THAT THIS ANNOTATION MAY GO AWAY IN UPCOMING RELEASES.  *\/ @Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS) @Retention(AnnotationRetention.BINARY) public actual annotation class ThreadLocal  \/**  * Marks a top level property with a backing field as immutable.  * It is possible to share the value of such property between multiple threads, but it becomes deeply frozen,  * so no changes can be made to its state or the state of objects it refers to.  *  * The annotation has effect only in Kotlin\/Native platform.  *  * PLEASE NOTE THAT THIS ANNOTATION MAY GO AWAY IN UPCOMING RELEASES.  *\/ @Target(AnnotationTarget.PROPERTY) @Retention(AnnotationRetention.BINARY) public actual annotation class SharedImmutable <\/code><\/pre>\n<p>  \u0412 \u0438\u0442\u043e\u0433\u0435, \u0432\u043d\u0435\u0441\u044f \u0432\u0441\u0435 \u043f\u0440\u0430\u0432\u043a\u0438, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u0435 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e \u043d\u0430 \u043e\u0431\u0435\u0438\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/no\/sq\/im\/nosqimyllh39tu_7eh7yzymd0ju.png\"><\/p>\n<p>  \u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 github.com\/anioutkazharkova\/movies_kmp<br \/>  <a href=\"https:\/\/tproger.ru\/articles\/creating-an-app-for-kotlin-multiplatform\/\" rel=\"nofollow\">tproger.ru\/articles\/creating-an-app-for-kotlin-multiplatform<\/a><br \/>  <a href=\"https:\/\/github.com\/JetBrains\/kotlin-native\" rel=\"nofollow\">github.com\/JetBrains\/kotlin-native<\/a><br \/>  <a href=\"https:\/\/github.com\/JetBrains\/kotlin-native\/blob\/master\/IMMUTABILITY.md\" rel=\"nofollow\">github.com\/JetBrains\/kotlin-native\/blob\/master\/IMMUTABILITY.md<\/a><br \/>  <a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\/issues\/462\" rel=\"nofollow\">github.com\/Kotlin\/kotlinx.coroutines\/issues\/462<\/a><br \/>  <a href=\"https:\/\/helw.net\/2020\/04\/16\/multithreading-in-kotlin-multiplatform-apps\/\" rel=\"nofollow\">helw.net\/2020\/04\/16\/multithreading-in-kotlin-multiplatform-apps<\/a><\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/533952\/\"> https:\/\/habr.com\/ru\/post\/533952\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\">\u0414\u043e\u0431\u0440\u043e\u0433\u043e \u0432\u0441\u0435\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0443\u0442\u043e\u043a! \u0421 \u0432\u0430\u043c\u0438 \u044f, \u0410\u043d\u043d\u0430 \u0416\u0430\u0440\u043a\u043e\u0432\u0430, \u0432\u0435\u0434\u0443\u0449\u0438\u0439 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u00abUsetech\u00bb.<br \/>  <a href=\"https:\/\/habr.com\/ru\/post\/533864\/\">\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u0430 \u043f\u0440\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 Kotlin Multiplatform. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0440\u0430\u0441\u0448\u0430\u0440\u0438\u0432\u0430\u0435\u043c\u044b\u043c \u043e\u0431\u0449\u0438\u043c \u043a\u043e\u0434\u043e\u043c, \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u044f \u0432\u0441\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043f\u043e\u0442\u043e\u043a\u0430\u043c\u0438 \u0432 \u043e\u0431\u0449\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443. <br \/>  \u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0433\u043b\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 Ktor, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u0437\u044f\u043b\u0430 \u043d\u0430 \u0441\u0435\u0431\u044f \u0432\u0441\u044e \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u0438 \u0432 \u0441\u0435\u0442\u0435\u0432\u043e\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0435. \u042d\u0442\u043e \u0438\u0437\u0431\u0430\u0432\u0438\u043b\u043e \u043d\u0430\u0441 \u043e\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c DispatchQueue \u043d\u0430 iOS \u0432 \u0442\u043e\u043c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043d\u043e \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u043d\u0430\u043c \u0431\u044b \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0442\u0432\u0435\u0442\u0430. \u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 Android \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 MainScope \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 suspended \u0444\u0443\u043d\u043a\u0446\u0438\u0438.   <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-315173","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/315173","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=315173"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/315173\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=315173"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=315173"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=315173"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}