• Корутины стэковые - безстековые, пул потоков, протопоток?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    foonfyrick, там в корутинах половина библиотеки экспериментальная, нестабильная, опциональная и тд.
  • Можно ли любое GUI положение сперва реализовать в консольном варианте, а потом уже привязывать к нему GUI?

    Борланд билдер и его VCL была самой божественной WYSIWYG системой для рисования окошек. Всё работало нормально, в отличие от современных кривых редакторов.
  • Корутины стэковые - безстековые, пул потоков, протопоток?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    foonfyrick, Короче, чтобы перестать задавать такие вопросы, нужно приобрести привычку читать код. И научиться его читать, отбрасывая ненужные подробности, чтобы вникнуть в суть. Единственный способ этому научиться - читать код. Постепенно научишься.
  • Корутины стэковые - безстековые, пул потоков, протопоток?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    Это всё писать значительно дольше, чем прощёлкать хоткеями по ссылкам в коде и посмотреть, что происходит. Это всё детали реализации, которые могут меняться(но есть комментарии, которые описывают, как оно должно работать).
    Дебаггером тоже можно - остановиться на бряке посреди запущенной корутины, и посмотреть, на каком треде происходит дело. Ну, будет реализация какого-то воркера, собственно.
  • Корутины стэковые - безстековые, пул потоков, протопоток?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    foonfyrick, Ну да, их создает библиотека kotlinx. Дебаггер тут не нужен.
    Что тебе известно? Я уже тебе сказал, что для выполнения на другом потоке проще всего использовать Dispatchers.Default. Ну, прямо в IDE же доступны исходники, заходишь и смотришь, что это:
    public actual object Dispatchers {
        /**
         * The default [CoroutineDispatcher] that is used by all standard builders like
         * [launch][CoroutineScope.launch], [async][CoroutineScope.async], etc
         * if no dispatcher nor any other [ContinuationInterceptor] is specified in their context.
         *
         * It is backed by a shared pool of threads on JVM. By default, the maximal level of parallelism used
         * by this dispatcher is equal to the number of CPU cores, but is at least two.
         * Level of parallelism X guarantees that no more than X tasks can be executed in this dispatcher in parallel.
         */
        @JvmStatic
        public actual val Default: CoroutineDispatcher = createDefaultDispatcher()

    Это объект, у которого пропертя, которая просто создается вызовом функции. Cmd+Click по ней(у меня такой хоткей, не знаю, как у тебя).
    Окай, смотрим
    internal fun createDefaultDispatcher(): CoroutineDispatcher =
        if (useCoroutinesScheduler) DefaultScheduler else CommonPool


    useCoroutinesScheduler описана немного выше, это системная проперти:
    internal val useCoroutinesScheduler = systemProp(COROUTINES_SCHEDULER_PROPERTY_NAME).let { value ->
        when (value) {
            null, "", "on" -> true
            "off" -> false
            else -> error("System property '$COROUTINES_SCHEDULER_PROPERTY_NAME' has unrecognized value '$value'")
        }
    }


    не вдаваясь в подробности, у тебя будет либо DefaultScheduler, либо CommonPool. Можно посмотреть оба, или выяснить значение этой проперти(я, например, сходу не скажу, какое она имеет значение).

    Посмотрим DefaultScheduler. Cmd+click
    internal object DefaultScheduler : ExperimentalCoroutineDispatcher()

    никаких осмысленно переопределенных методов нет, значит вся соль в его предке. Cmd+click по ExperimentalCoroutineDispatcher.

    @InternalCoroutinesApi
    public open class ExperimentalCoroutineDispatcher(
        private val corePoolSize: Int,
        private val maxPoolSize: Int,
        private val idleWorkerKeepAliveNs: Long,
        private val schedulerName: String = "CoroutineScheduler"
    ) : ExecutorCoroutineDispatcher() {
        public constructor(
            corePoolSize: Int = CORE_POOL_SIZE,
            maxPoolSize: Int = MAX_POOL_SIZE,
            schedulerName: String = DEFAULT_SCHEDULER_NAME
        ) : this(corePoolSize, maxPoolSize, IDLE_WORKER_KEEP_ALIVE_NS, schedulerName)
    
        @Deprecated(message = "Binary compatibility for Ktor 1.0-beta", level = DeprecationLevel.HIDDEN)
        public constructor(
            corePoolSize: Int = CORE_POOL_SIZE,
            maxPoolSize: Int = MAX_POOL_SIZE
        ) : this(corePoolSize, maxPoolSize, IDLE_WORKER_KEEP_ALIVE_NS)
    
        override val executor: Executor
            get() = coroutineScheduler
    
        // This is variable for test purposes, so that we can reinitialize from clean state
        private var coroutineScheduler = createScheduler()
    
        override fun dispatch(context: CoroutineContext, block: Runnable): Unit =
            try {
                coroutineScheduler.dispatch(block)
            } catch (e: RejectedExecutionException) {
                // CoroutineScheduler only rejects execution when it is being closed and this behavior is reserved
                // for testing purposes, so we don't have to worry about cancelling the affected Job here.
                DefaultExecutor.dispatch(context, block)
            }
    
        override fun dispatchYield(context: CoroutineContext, block: Runnable): Unit =
            try {
                coroutineScheduler.dispatch(block, tailDispatch = true)
            } catch (e: RejectedExecutionException) {
                // CoroutineScheduler only rejects execution when it is being closed and this behavior is reserved
                // for testing purposes, so we don't have to worry about cancelling the affected Job here.
                DefaultExecutor.dispatchYield(context, block)
            }
    
        override fun close(): Unit = coroutineScheduler.close()
    
        override fun toString(): String {
            return "${super.toString()}[scheduler = $coroutineScheduler]"
        }


    Много букв, но в общем, в глаза бросается executor. Если посмотреть, кого он оверрайдит, там написано
    /**
         * Underlying executor of current [CoroutineDispatcher].
         */
        public abstract val executor: Executor

    То есть это тот executor, на котором непосредственно всё будет выполняться, что ты запустишь на этом диспатчере.

    Дальше, естественно, смотрим private var coroutineScheduler = createScheduler()
    Cmd+click
    private fun createScheduler() = CoroutineScheduler(corePoolSize, maxPoolSize, idleWorkerKeepAliveNs, schedulerName)

    nternal class CoroutineScheduler(
        @JvmField val corePoolSize: Int,
        @JvmField val maxPoolSize: Int,
        @JvmField val idleWorkerKeepAliveNs: Long = IDLE_WORKER_KEEP_ALIVE_NS,
        @JvmField val schedulerName: String = DEFAULT_SCHEDULER_NAME
    ) : Executor, Closeable {


    Вот это уже непосредственно реализация executor'a.
    Здесь можно обнаружить такую пропертю
    /**
         * State of worker threads.
         * [workers] is array of lazily created workers up to [maxPoolSize] workers.
         * [createdWorkers] is count of already created workers (worker with index lesser than [createdWorkers] exists).
         * [blockingTasks] is count of pending (either in the queue or being executed) tasks
         *
         * **NOTE**: `workers[0]` is always `null` (never used, works as sentinel value), so
         * workers are 1-indexed, code path in [Worker.trySteal] is a bit faster and index swap during termination
         * works properly
         */
        @JvmField
        val workers = AtomicReferenceArray<Worker?>(maxPoolSize + 1)


    Worker это уже непосредственно поток:
    internal inner class Worker private constructor() : Thread() {


    Дальше в этом классе можно копаться и смотреть, что как делают взрослые серьёзные дяди. Там сложный многопоточный низкоуровневый библиотечный код. Но, собственно, не вникая в детали, вот они твои потоки, которые создаются. Абсолютно аналогично в CommonPool можешь посмотреть что происходит
  • Нужно ли делать DI для простых Kotlin объектов?

    zagayevskiy
    @zagayevskiy Куратор тега Android
    Tsudzukeru, почему бы ViewModel тоже не держать в графе? В модуле сделай Provides- метод, в который прими фабрику и фрагмент, а верни вьюмодель. Это с точки зрения DI.
    А с точки зрения архитектуры, конечно, адаптер не должен знать ни про какую ViewModel. У него должен быть метод для обновления списка элементов и всё, а работа с вьюмоделью должна быть вне его.
  • Почему не создаётся компонент Dagger, при написании интерфейса на Kotlin?

    zagayevskiy
    @zagayevskiy Куратор тега Android
    Tsudzukeru, да, конечно. Понимаешь, то, что этому фрагменту понадобится что-то из графа - это дело времени. И получится, что это всё равно надо переписывать.
    Одновременное использование @Inject в конструктор и @Inject полей - это капец дичь. Так быть не должно никогда.
  • Корутины стэковые - безстековые, пул потоков, протопоток?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    foonfyrick, ппц. Ты определись, ты изучаешь корутины в котлине и детали их реализации, или ты изучаешь абстрактную теорию, которая нигде не реализована, и похожие фичи во всех языках и фреймворках?
  • Это нормальная логика работы приложения?

    zagayevskiy
    @zagayevskiy Куратор тега Android
    Степан, то что ты будешь постоянно грузить сеть зря. И будешь постоянно дергаться в бекграунде. ДЛя этой задачи есть специальный инструмент, надо его использовать.
  • Корутины стэковые - безстековые, пул потоков, протопоток?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    1) откуда ты это взял?
    2) а в коде посмотреть? Система ничего не знает про корутины.
    3) что такое протопоток?
    4) какие ещё корутины со стеком и без стека?
    5) чего?
    6) чегоооо?
  • Как выбирать, создать поток или корутину?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    Dmtm, я думаю, если ты уверен, что тебе необходим максимальный приоритет, то тебе не составит труда найти эту информацию по каждой"альтернативе".
  • Android Studio как добавить значения в поле EditText, при нажатии на кнопку?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    Ну то есть ты криво наверстал что-то в xml. На другом устройстве всё разъедется. Теперь надо писать код.
  • Где больше платят, в разработке на ruby(RoR) или в тестировании?

    giftedtatar, а зачем тебе реалии зп? Раз такой вопрос, значит ни в одной из этих сфер ты не шаришь. Идти в айти за большой зп бессмысленно. Надо этим гореть.
  • Корутины, Runnable,DispatchedContinuation?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    foonfyrick, нет. Лямбда это функция без имени. То что там раннабл и тд вообще минорные детали реализации.
    Корутина это не вот этот твой блок кода. Это более сложная вещь. Читай доку до просветления.
    Когда ты делаешь Thread { ... }.start(), ты же не говоришь, что { ... } это поток, правильно? Так и здесь, есть билдеры корутин, launch, async, и тд, которые запускают корутину. В них ты передаешь suspend lambda, которая будет выполняться в контексте корутины. Саму "корутину" ты тут как бы и не видишь, она - это вся машинерия, которая позволяет выполнять асинхронный код, написанный в императивном стиле. Нет ни ключевого слова coroutine, ни класса Coroutine, который был бы тебе доступен, чтобы его потрогать. Есть suspend fun/lambda, и есть компиляторная магия, которая превращает вызовы suspend функций в гигантский конечный автомат с коллбеками(continuation). Говорят, что корутины можно рассматривать как легковесные потоки. Но на самом деле они не потоки.

    Короче, несмотря на внешнюю простоту, это офигенно сложная концепция.
  • Anroid, как записать json используя Retrofit2, RxJava2?

    zagayevskiy
    @zagayevskiy Куратор тега Android
    Eugesha1998, ну вот с этого надо было начинать.. ответил.
  • Корутины, Runnable,DispatchedContinuation?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    foonfyrick, нет, это лямбда. Да, она туда передаётся, и выполнятся в итоге.
  • Anroid, как записать json используя Retrofit2, RxJava2?

    zagayevskiy
    @zagayevskiy Куратор тега Android
    Eugesha1998, а дальше-то что? Где чтение этой переменной?
  • Anroid, как записать json используя Retrofit2, RxJava2?

    zagayevskiy
    @zagayevskiy Куратор тега Android
    В какую переменную? И что тебе конкретно мешает это сделать?