Ответы пользователя по тегу Kotlin
  • Как создать виждет на фрагменте (fragment) android studio?

    zagayevskiy
    @zagayevskiy Куратор тега Android
    Android developer at Yandex
    Читай logcat, там будет стектрейс твоей ошибки. Наверняка какой-то банальный баг. Здесь полфорума знает как "это" реализовать, но никто за тебя писать не будет. И более конкретного ответа без уточнений ты не получишь.
    Ответ написан
    Комментировать
  • Имеет ли смысл начинать учить Kotlin, если вовсе не знаком с Java?

    zagayevskiy
    @zagayevskiy Куратор тега Android
    Android developer at Yandex
    Котлин можно изучать не зная джавы. Это факт. Под андроид он завязан на JVM, но для базового уровня это неважно. Потом всегда можно подтянуть. Нужно будет в итоге уметь читать джаву, но это не абы какой рокет сайнс.

    Другой вопрос, что
    Kotlin, который по заявлением многих значительно легче и проще, нежели Java.

    Это не так. Котлин не проще джавы. На нём сильно выше плотность кода, у него значительное количество фичей, которых в джаве просто нет. Когда тебе опытный человек говорит, что писать на котлине проще и приятнее, чем на джаве, это, скорее всего, правда, но это не значит, что котлин проще в изучении. Я, например, при переходе обратно в джавовые файлы испытываю боль и страдания. То, что можно было написать одной строкой, превращается в 5-10, всё неудобно и неприятно.
    Ответ написан
    2 комментария
  • Как реализовать переход textView на новую строку?

    zagayevskiy
    @zagayevskiy Куратор тега Java
    Android developer at Yandex
    Заменить пробелы неразрывными пробелами.
    Ответ написан
    Комментировать
  • Почему предупреждают и говорят, что Kotlin нельзя выучить без знаний Java?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    Android developer at Yandex
    Я не знаю, почему в этих курсах такое требование. Котлин отдельный язык, и его можно учить без джавы. Сначала это был чисто JVM-язык, но на данный момент его можно использовать не только на JVM, тк есть Kotlin/Native и Kotlin/JS.
    Также как Scala и Groovy другие JVM-языки.
    В Kotlin/JVM сильно используется стандартная библиотека джавы, и вот её придется изучить по итогу. Также его можно декомпилировать и смотреть джавовый код, который получается. Для этого придется изучить джаву, но это не первоочередная задача.

    Когда в курсе в предусловии есть какие-то языки, это значит, будут проводиться аналогии, ты их не поймёшь, и будет сложнее. Они предполагают, что это не первый твой язык. Имхо, если ты не прямо новичок, и какой-то язык знаешь, то такие курсы могут тебе подойти. Но, в принципе, котлин легко изучить, прочитав доку и порешав коаны.
    Ответ написан
    4 комментария
  • Как скачать картинку из URL и сделать его bitmap в kotlin?

    zagayevskiy
    @zagayevskiy Куратор тега Android
    Android developer at Yandex
    Использовать Glide.
    Ответ написан
    Комментировать
  • Ошибка Inappropriate blocking method call при http запросе в Kotlin. В чем проблема?

    zagayevskiy
    @zagayevskiy Куратор тега Java
    Android developer at Yandex
    Когда ты так делаешь, весь смысл корутин теряется. Фишка в том, что когда корутина саспендится, поток не блокируется. А ты внутри корутины используешь блокирующий метод. Возьми другой http клиент, ktor, он, вроде как, умеет нормально это делать.
    Ответ написан
    3 комментария
  • Callback и listener?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    Android developer at Yandex
    Listener(слушатель) это callback(обратный вызов), ждущий наступления некоего события. То что ты используешь лямбду вообще никаким образом не связано с потоками, с тем, кто перед кем вызовется. Когда вызовешь, тогда и будет.
    Listener и Observer это вопрос терминологии и наименования. Слушатель и обозреватель. По сути одно и тоже.
    Ответ написан
    Комментировать
  • Function вызов inline и константы?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    Android developer at Yandex
    На каком-то бытовом уровне схоже, конечно. Типа, и то, и другое встраивается. Но различия, конечно есть.
    Есть ситуации, когда компилятор обязан встроить inline функцию, потому что другого ему не позволит JVM, например:
    inline fun <reified T> f() {
        print(T::class.java.name)
    }

    reified дженерики поддерживаются только для inline функций, потому что в JVM на этапе выполнения никаких дженериков нет, и поэтому данную функцию можно использовать только с известным на момент компиляции типом. Тело функции встроится в место вызова и всё хорошо.

    А вот если у тебя просто inline fun, вне зависимости от того, есть ли у неё функциональный параметр, то уже возможны варианты. При обычном вызове тело функции будет встроено, и на этом основаны всякие экстешны, они не просаживают произволительность. Но также ты можешь взять и передать эту функцию в другую в качестве параметра, и в этом случае ей просто некуда встраиваться:
    inline fun f() { ... }
    fun g(p: ()-> Unit) {
        p()
    }
    
    fun main() {
        f() // заинлайнена
        g(::f) // не заинлайнена
    }


    Если хочешь разобраться - смотри декомпилированный байткод, там всё есть. Ещё почитай про модификаторы noinline, crossinline.
    Ответ написан
    Комментировать
  • Как организовать подключение к серверу используя RxJava?

    zagayevskiy
    @zagayevskiy Куратор тега Java
    Android developer at Yandex
    Примерно так, только сначала все ресурсы освободи, а уже потом кидай onSuccess.
    Ну и совсем непонятно, что за хрень происходит с каким-то мутабельным стейтом. Такого лучше избегать.
    Например, можно сделать так - вместо connectToServer, которая ничего не возвращает, но зато мутирует стейт, можно сделать функцию, которая ничего не будет мутировать, но зато будет возвращать Observable состояний(Loading/Error/Success/etc). К этой функции будет происходить подписка и уже обработка состояний.
    Ответ написан
    Комментировать
  • Изучение андроид разработки что выбрать Java или kotlin?

    zagayevskiy
    @zagayevskiy Куратор тега Java
    Android developer at Yandex
    Уже 100500 раз отвечен этот вопрос. Выбрать котлин. Это вполне отдельный язык, официальный язык для андроида. Можно учить его отдельно от джавы, вовсе не нужно страдать с самого начала. Потом, когда ты его изучишь, и твоя компетентность вырастет, можно будет доизучить особоенности JVM, джавовые коллекции и тд. На первых парах это совершенно не нужно.
    Ответ написан
  • Produce{} vs iterator{}?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    Android developer at Yandex
    Ничего, iterator это верхнеуровневый билдер. Ты код-то пробовал писать, или просто читаешь эту лабуду?
    iterator {
        yield(1)
        yield(2)
        yield(3)
    }.forEach { i -> print(i) }
    Ответ написан
    1 комментарий
  • CoroutineScope(Dispatchers.Main).launch{} vs CoroutineScope(Dispatchers.Main).launch(DispathersMain){}?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    Android developer at Yandex
    1) имя корутины нужно только для дебага

    2) никакого конструктора лонча нет, это просто функция на CoroutineScope. Разницы между данными примерами нет. Передать диспатчер можно в случае, если ты хочешь лончить в другой диспатчер.

    3) это вроде повтор второго вопроса. Разверну немного. Если в CoroutineScope передать диспатчер(D), то все лончи без дополнительных диспатчеров будут происходить на диспатчере D. A если не передавать, то все такие лончи будут происходить на Dispatchers.Default, то есть для андроида - на диспатчере, у которого несколько потоков, и на котором можно выполнять тяжёлые вычисления.
    Лончи, в которые передан диспатчер, будут выполнены на этом диспатчере.

    Как-то так. Это на самом деле сложная и запутанная тема. За внешней простотой скрывается очень сложная машинерия. Ты пока вскрыл довольно простые вещи.
    Ответ написан
    Комментировать
  • Как вызвать Rx метод внитри другого Rx метода?

    zagayevskiy
    @zagayevskiy Куратор тега Java
    Android developer at Yandex
    Во-первых, изменяемые данные в Rx-стриме это очень, очень плохо. С этим можно обрести кучу багов. Данные должны быть неизменяемыми.
    Во-вторых тебе понадобится combineLatest, который принимает список Observable. А список ты получишь из своего списка видео.
    Ответ написан
    Комментировать
  • Какую часть Java занимает в мобильной разработке, если код написан на Kotlin?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    Android developer at Yandex
    Начинать с джавы необязательно, можно и сразу с котлина.
    Котлин под Андроид компилируется в джава-байткод. Также он использует джавовую стандартную библиотеку(коллекции, например). Поэтому с джавой ты так или иначе столкнешься, но, в принципе, это можно и по ходу раскурить, не обязательно страдать с самого начала. Когда уровень твоей компетенции вырастет, ты поймёшь, где пробелы и чего ты не понимаешь. Тогда изучишь джаву и устройство jvm.

    Свифта в айос на первых парах хватит с головой. Там есть Objective-C, но ты с ним не столкнешься, разве что полезешь во что-то низкоуровневое.
    Ответ написан
    4 комментария
  • Как вызвать retry() для асинхронного метода, изменив параметры вызова этого метода?

    zagayevskiy
    @zagayevskiy Куратор тега Java
    Android developer at Yandex
    Всё происходит правильно. AsyncMethod(param1,param2,ApiKeyStore.CurrentKey) вызывается только один раз, и при каждом retry происходит переподписка к его результату. Поэтому ключ не меняется. Нужно сделать так, чтобы при retry вызывался сам метод, а значит - использовать Observable.defer:
    Observable.defer { AsyncMethod(param1,param2,ApiKeyStore.CurrentKey) } 
    .doOnError{
        ApiKeyStore.getNextApiKey()
    }
    .retry(ApiKeyStore.attemptsNumber)

    Теперь при retry переподписка будет к defer, и каждый раз будет вызываться AsyncMethod с новыми параметрами.
    Как-то так.
    Ответ написан
    1 комментарий
  • Почему этот код не выдает ошибку "Val cannot be reassigned"?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    Android developer at Yandex
    Никогда сильно об этом не задумывался. Судя по всему, частично скопировали поведение из джавы, а частично просто ошиблись в дизайне языка на ранней стадии проектирования. И теперь должны это поддерживать. Причин так делать не вижу, control flow analysis позволяет избежать переприсваивания. Кстати, если вызовешь showTestParam() в самом начале первого init-блока, там ещё и null будет:(
    Ответ написан
  • Как использовать setOnClickListener во фрагменте вкладки?

    zagayevskiy
    @zagayevskiy Куратор тега Android
    Android developer at Yandex
    Ты инфлейтишь одну вьюху, ищешь в ней кнопку, потом инфлейтишь новую вьюху и возвращаешь её. Первый инфлейт просто выкидывается. Возвращай его результат, и всё заработает.
    Ответ написан
  • Какая лучшая книга по Kotlin?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    Android developer at Yandex
    Документация + коаны. Книга не нужна.
    Ответ написан
  • Как работает as? В чем отличие от преобразования типов?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    Android developer at Yandex
    Нет, ты неправильно понял. as это про отношение родитель-потомок, которым упомянутые тобой Int, Long и Char не связаны. Поэтому ты получаешь ошибки. Что это значит: у тебя есть значение, имеющее тип "родитель"и ты хочешь привести его к типу "потомок".
    Например:
    fun f(n: Number): Int{
       return n as Int
    }
    
    f(10) // 10
    f(10L) // ClassCastException

    По второму примеру ты можешь понять, что делать приведение типов, если ты точно не знаешь, какой тип имеет инстанс, чревато ошибками в рантайме.
    Поэтому есть форма as?, которая в случае неудачи возвращает null. А также есть оператор is, который проверяет, является ли объект инстансом определенного класса:
    val x = 10
    x is Int == true
    x is Number == true
    x is Any == true
    x is Long == false
    x as Int // redundent
    val y: Long? = x as? Long //== null

    Кроме того, в котлине есть такая прекрасная вещь, как смарткасты(умное приведение типов). Что это значит. Если компилятор видит, что ты проверил тип значения и это значение не может измениться, то он выводит соответвующий тип сам, и явный каст(as) не нужен. Это работает для условных выражений, if, when, elvis-operator, также если ты ранее делал каст.
    val x: Any = ...
    if (x is String) x.substring(0, 10)
    if (x is Int) x + 10
    
    x as Long // Long или ClassCastException
    x + 10L // до этой точки выполнение дойдёт только в случае успешного каста.

    И конечно это всё прекрасно работает с пользовательскими типами, божественно вместе с sealed классами:
    sealed class B
    class D1(val x: Int): B()
    class D2(val y: String): B()
    object D3: B()
    
    fun f(b: B){
      when (b){
        is D1 -> b.x 
        is D2 -> b.y
        is D3 -> D3
      }
    }

    Это удобно для возвращения разных значений, обработки ошибок и тд.

    Таким образом, использования as имеет смысл в довольно ограниченном числе случаев. Когда компилятор не может доказать что-то, но ты это точно знаешь. Например, в случае мутабельной проперти, или функции, возвращающей одно и то же значение.

    Упомянутый тобой toInt это не преобразование типа, а обычная функция, которая возвращает новый тип по неким правилам.
    Ответ написан
    Комментировать
  • Почему рекомендуется пользоваться неизменяемыми списками?

    zagayevskiy
    @zagayevskiy Куратор тега Kotlin
    Android developer at Yandex
    Речь не только о списках. Последнее время есть тенденция на всё иммутабельное, так как проще пользоваться, меньше ошибок. Это так же связано с прорастанием везде Rx(Reactive eXtensions), это стримы данных, и эти данные должны быть иммутабельными для адекватной работы с ними.
    Если говорить про котлин, то там ребята в стандартной библиотеке сделали прекрасные параллельные иерархии изменяемых и неизменяемых коллекций. Везде, где это возможно, в том числе в апи, лучше использовать неизменяемые коллекций. Так проще читать код и разбираться в том, как он работает. Легче избежать ошибок, если ты видишь, что какой-то класс отдает List, значит он ожидает, что изменять его нельзя. А если отдает MutableList - значит, ожидает, что ты можешь его изменять.
    Ответ написан
    Комментировать