- В конце вопроса обновление .Теперь я должен включить и отключить ошибку с одним изменением строки в крошечном проекте со всем кодом, транскрибированным ниже.
- Ответ из Алексей Романов блестящийПроверьте в конце вопроса.Это удивительная и неизвестная особенность среды Android Studio .
Я обнаружил очень странную ошибку в Kotlin при использовании обновленной Android 3.4.2 .
Сначала я запустил свойпроверить код на моем компьютере (не Android ), используя основные модули в любом файле kotlin в моем единственном модуле.Он всегда работает для меня, но начал выдавать ошибку, которую я комментирую ниже, а затем еще одну ошибку, которая больше не позволяет запускать основной модуль.
Поиск в Stack Overflow
, один пользователь, как утверждалосьчто последняя описанная ошибка заканчивается, когда кто-то использует test
файлы в папке java
(не Android test
файлы)
Однако продолжает выдавать первую ошибку, которую я прокомментировал выше, которую мне удалосьуменьшите до следующего схематического примера:
class Cl(
var a:Int=0
)
var vCl = arrayListOf<Cl>()
И основной модуль:
fun main(){
println("start")
vCl.clear() // error points to this line
println("ok")
}
Я просто указываю на fun main()
строку в test файле и нажимаюзеленый значок.
Сообщение об ошибке
Exception in thread "main" java.lang.ExceptionInInitializerError
Внезапно ошибка прекращается, когда я изменил один глобальный оператор из одного файла в другой файл (в верхней части, вне какого-либо класса или функции).
var timings = TimingLogger("MyTag", "Your")
Это безумие.Я волнуюсь!
Обновление:
=======
Я сделал newerror
, новый крошечный проект с однимМодуль для воспроизведения ошибки, описанной в этом вопросе.Ниже приведен полный код:
Gradle : без изменений после создания проекта.
AndroidManifest.xml : без изменений после создания проекта.
activity_main.xml : Это голое тело, потому что все мои представления созданы динамически:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/myLayout"
android:textAllCaps="false"
android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=
"br.com.greatsolutions.paulo.myerror.MainActivity">
</RelativeLayout>
Код MainActivity.kt :
package br.com.greatsolutions.paulo.myerror
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
compiler.kt код
package br.com.greatsolutions.paulo.myerror
import android.util.TimingLogger
var timings = TimingLogger("MyTag", "Your")
class Cl(
var a:Int=0
)
var vCl = arrayListOf<Cl>()
Наконец test.kt код:
package br.com.greatsolutions.paulo.myerror
fun main(){
println("start")
vCl.clear()
println("ok")
}
Полныйсообщение об ошибке при запуске кода test.kt на моем компьютере (не в Android):
start
Exception in thread "main" java.lang.ExceptionInInitializerError
at br.com.greatsolutions.paulo.myerror.TestKt.main(test.kt:5)
at br.com.greatsolutions.paulo.myerror.TestKt.main(test.kt)
Caused by: java.lang.RuntimeException: Stub!
at android.util.TimingLogger.<init>(TimingLogger.java:59)
at br.com.greatsolutions.paulo.myerror
.CompilerKt.<clinit>(compiler.kt:5)
... 2 more
И, опять же, если я помещу нижеприведенное объявление в MainActivity.kt и снова запустите test.kt на моем компьютере ...
var timings = TimingLogger("MyTag", "Your")
... и ошибка исчезнет!
start
ok
Дляте, кто хочет видеть, чтобы верить:
Заключение : Теперь я знаю, как избежать этой сумасшедшей ошибки, но я не понимаюне понимаю, почему это работает!Теоретически, исходный файл, который я использую для своих объявлений, должен быть взаимозаменяемым, потому что все файлы находятся в одном модуле!
Solution of puzzle
Алексей Романов ударил ногтем по голове!
Я исследовал немного больше и обнаружил, что Android Studio выполняет объявления в файле, только если какая-либо переменная области была использована в компьютерном тесте.
Когда
var timings = TimingLogger("MyTag", "Your")
находится внутри MainActivity.kt
, ошибка не отображается.
После того, как я вставил в этот файл следующий код:
open class Fool(val a:Int=5){
init { println("fool") }
}
class SuperFool(a:Int=8):Fool(a) {
init { println("what a big fool") }
}
var v = SuperFool()
Когда я ставлю println(v.a)
, мой код в test.kt становится:
package br.com.greatsolutions.paulo.myerror
fun main(){
println("start")
println(v.a) // new line
vCl.clear()
println("ok")
}
И он выдает ту же ошибку, что и раньше!Выньте эту строку и без ошибок снова!
Решение состоит в том, что если в вашем проекте есть объявление какой-либо переменной в классе Android , вы ДОЛЖНЫ использовать lateinit
и просто инициализировать в другой точке кода, которая не будет работать в тесте.выполнение.
В этом случае можно сделать
lateinit var timings:TimingLogger
и поместить инициализацию в другое место (например, внутри onCreate
в MainActivity
классе. В моем случае, непосредственно перед1-й вызов addSplit
, один из методов TimingLogger
class
timings = TimingLogger("MyTag", "Your")
Теперь мой тестовый код плавно печатает
start
fool
what a big fool
ok