Ответы пользователя по тегу Kotlin
  • Почему приложение вылетает после перехода на третье Activity?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Вообще переход на новую Activity делается по-другому. Почитай книгу Android. Программирование для профессионалов, много вопросов отпадут. Только обзаведись английской версией, чтобы смотреть в неё, когда не понятно, что имеется ввиду под некоторыми словами. И подписку на клики в XML лучше не делать. Методы именуются с маленькой буквы (camelCase).

    Инструкция, как ловить исключения
    Выполни по инструкции ниже всё и потом ты сможешь смотреть, какое произошло исключение, если приложение будет крашиться. Просто ставь точку останова на строке println(message) и когда сработает обработчик не перехваченного исключения, то там ты и посмотришь, что в нём написано.

    Создай класс TestAppUncaughtExceptionHandler
    package com.example.test
    
    import java.lang.Thread.UncaughtExceptionHandler
    
    class TestAppUncaughtExceptionHandler : UncaughtExceptionHandler {
    	override fun uncaughtException(thread: Thread, ex: Throwable) {
    		val message = "Thread name: ${thread.name}, Exception: ${ex.fillInStackTrace()}"
    		// На строке ниже ставь точку останова (breakpoint) и смотри, что написано в исключении.
    		println(message) 
    	}
    }


    Создай класс TestApplication
    package com.example.test
    
    import android.app.Application
    
    // Указывается в манифесте, чтобы работал
    class TestApplication : Application() {
    	override fun onCreate() {
    		super.onCreate()
    		
    		Thread.setDefaultUncaughtExceptionHandler(TestAppUncaughtExceptionHandler())
    	}
    }


    В AndroidManifest.xml файл добавь android:name=".TestApplication"

    Пример AndroidManifest.xml (многое удалено для краткости)
    <?xml version="1.0" encoding="utf-8"?>
    <manifest package="com.example.test"
    	xmlns:android="http://schemas.android.com/apk/res/android">
    
    	<application
    		android:name=".TestApplication">
    		<activity
                       ...
    		</activity>
    	</application>
    
    </manifest>
    Ответ написан
    1 комментарий
  • Как преобразовать время в миллисекунды в kotlin?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    import java.time.LocalTime
    import java.time.format.DateTimeFormatter
    
    // ---
    val formatter = DateTimeFormatter.ISO_LOCAL_TIME
    val time = LocalTime.parse("16:07:08.900700901", formatter)
    println(time.nano)
    Ответ написан
  • Установка библиотеки из Git?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Файл build.gradle.kts (Kotlin). Читай ниже и смотри скриншоты.
    import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
    
    plugins {
        kotlin("jvm") version "1.7.0"
    }
    
    group = "org.example"
    version = "1.0-SNAPSHOT"
    
    repositories {
        maven {
            url = uri("https://jitpack.io")
        }
        mavenCentral()
    }
    
    dependencies {
        implementation("io.github.kotlin-telegram-bot.kotlin-telegram-bot:telegram:6.0.7")
        testImplementation(kotlin("test"))
    }
    
    tasks.test {
        useJUnitPlatform()
    }
    
    tasks.withType<KotlinCompile> {
        kotlinOptions.jvmTarget = "1.8"
    }


    Файл build.gradle (Groovy)
    plugins {
        id 'org.jetbrains.kotlin.jvm' version '1.7.0'
    }
    
    group = 'org.example'
    version = '1.0-SNAPSHOT'
    
    repositories {
        maven { url "https://jitpack.io" }
        mavenCentral()
    }
    
    dependencies {
        implementation 'io.github.kotlin-telegram-bot.kotlin-telegram-bot:telegram:6.0.7'
        testImplementation 'org.jetbrains.kotlin:kotlin-test'
    }
    
    test {
        useJUnitPlatform()
    }
    
    compileKotlin {
        kotlinOptions.jvmTarget = '1.8'
    }
    
    compileTestKotlin {
        kotlinOptions.jvmTarget = '1.8'
    }


    Создаём новый проект, где в качестве языка Gradle скриптов выбираем Kotlin (его банально легче понять, так как там всё типизировано и можно просто перейти и посмотреть исходник.
    62b23c308102b293725073.png

    Если проект использует для Gradle скриптов не Kotlin, а Groovy, то нужно нажать кнопку, на которую показывает стрелка. Может быть не во всех случаях так. В общем, по ситуации.
    62b23c5780200189084481.png

    Готово
    62b23cfdd078d277180730.png
    Ответ написан
  • Как исправить ошибку? "Переменная не инициализирована?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Исправил ошибку. Простым readLine здесь не обойтись. Написал функцию requestUserInputAsInt, которая перезапрашивает ввод у пользователя, если введено не число или введённое число не попадает в диапазон.

    В целом я понял, что хочет реализовать автор и здесь нужно всё писать по-другому, но это придёт с опытом. Например, для характеристик героя и мира используй классы. Для совершения действий в мире можно использовать State Machine, при том лучше реализовать её так, чтобы можно было все состояния расписать в одном месте в декларативном виде (все переходы состояний, сами состояния в отдельных классах).

    Первое, что нагуглил. В целом, похоже на то, что я имел ввиду:
    Implement a state machine with kotlin using tinders library (ссылка)
    https://github.com/Tinder/StateMachine

    62ac6d647890a259916233.png
    Вдруг кому-то интересно: подсветка синтаксиса называется Visual Studio 2019 Dark + я сам добавил свои модификации, чтобы было похоже на подсветку для C# из Visual Studio 2022 для тёмной темы для языка C#

    val newLine: String = System.lineSeparator()
    val menu: List<String> = listOf("Пиво", "Пахлёбка ", "Супец")
    
    fun main(args: Array<String>) {
    	val hearth: Int = 5
    	val projectName: String = "Мечи Средиземья"
    	val defaultSteed: String = "- Скакуна нет "
    	val traktirName: String = "Рог Единорога"
    	val buyManName: String = "Эдгар"
    	val moneySum: Int = 23
    	val hasSteed: String = defaultSteed
    	val heroName: String = "Дионис"
    
    	println(projectName)
    	println(hasSteed)
    	println("Здоровье: $hearth")
    	println("Монет: $moneySum")
    	println("Главный герой прибыл в трактир $traktirName ${newLine}Вас приветствует  владелец трактира $buyManName")
    
    	try {
    		val message = "Выберите действие:${newLine}Открыть Меню - 1${newLine}Посмотреть в зеркало - 2"
    		when (requestUserInputAsInt(message, IntRange(1, 2))) {
    			1 -> println("Меню: $menu")
    			2 -> println("В зеркале герой увидел свое имя $heroName")
    		}
    	} catch (ex: Throwable) {
    		ex.printStackTrace()
    		println(ex)
    	}
    }
    
    /**
     * Запросить ввод пользователем целого числа. В случае неправильного ввода запрос будет осуществлён повторно.
     * @param message Сообщение, которое будет выведено на консоль, при первом и повторных запросах ввода.
     * @param range диапазон чисел, в которые должен попасть пользовательский ввод.
     * */
    fun requestUserInputAsInt(message: String? = null, range: IntRange? = null): Int {
    
    	range?.let {
    		if (it.first > it.last) throw IllegalArgumentException("first > last: (${it.first} > ${it.last})")
    	}
    
    	val result: Int
    	while (true) {
    		message?.let { println(it) }
    		
    		val line = readlnOrNull()
    		if (!line.isNullOrBlank()) {
    			val resultTemp: Int? = line.toIntOrNull()
    			if (resultTemp != null) {
    				if (range != null) {
    					if (resultTemp >= range.first &&
    						resultTemp <= range.last
    					) {
    						result = resultTemp
    						break
    					}
    				} else {
    					result = resultTemp
    					break
    				}
    			}
    		}
    	}
    
    	return result
    }
    Ответ написан
  • Как работает array.indices?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Удалился индекс 2, то есть элемент коллекции под индексом 2.
    index: 0: value: 1
    index: 1: value: 2
    index: 2: value: 3
    index: 3: value: 4
    index: 4: value: 5

    Если удалить индекс 2, то элемент 3 выведен не будет. Кажется логичным.

    Я открыл IntelliJ IDEA, зажал Ctrl (Cmd в MacOS) и нажал левой кнопкой мыши на знак - (минус). Попал в метод-расширение minus. Скопировал его и другие связанные методы. Получил точно такое же поведение (потому что фактически выполняется тот же самый код). Теперь можно начать отлаживать код, пройтись по методам пошагово и понять почему мы имеем такой результат. Ранее упомянутый метод minus - это метод, которого нет в исходном классе Iterable<T>, но его добавили в какой-то библиотеке. Это не новшество Kotlin, такие же методы-расширения можно создавать, например, в C#.

    623f0a3e1643d280918242.png

    fun main(args: Array<String>) {
    
        val numbers = intArrayOf(1, 2, 3, 4, 5)
    
        // Исходный пример
        for (index in numbers.indices - 2) {
            println("index: $index: value: ${numbers[index]}")
        }
    
        println("------")
    
        // Пример-объяснение. Были взяты оригинальные методы расширения
        // и вынесены сюда для удобства отладки и наглядности.
        for (index in minus(numbers.indices, 2)) {
            println("index: $index: value: ${numbers[index]}")
        }
    }
    
    fun <T> minus(iterable: Iterable<T>, element: T): List<T> {
        val arraySize = collectionSizeOrDefault(iterable, 10)
        val result = ArrayList<T>(arraySize)
        var removed = false
        return filterTo(iterable, result) {
            if (!removed && it == element) {
                removed = true; false
            } else true
        }
    }
    
    fun <T> collectionSizeOrDefault(iterable: Iterable<T>, default: Int): Int =
        if (iterable is Collection<*>) iterable.size else default
    
    fun <T, C : MutableCollection<in T>> filterTo(iterable: Iterable<T>, destination: C, predicate: (T) -> Boolean): C {
        for (element in iterable) if (predicate(element)) destination.add(element)
        return destination
    }


    Лучше вынести из выражение, чтобы удобнее было дебажить и смотреть, что там к чему:
    val result: List<Int> = minus(numbers.indices, 2)
        for (index in result) {
            println("index: $index: value: ${numbers[index]}")
        }


    Вывод:
    index: 0: value: 1
    index: 1: value: 2
    index: 3: value: 4
    index: 4: value: 5
    ------
    index: 0: value: 1
    index: 1: value: 2
    index: 3: value: 4
    index: 4: value: 5
    Ответ написан
    1 комментарий