【发布时间】:2019-07-10 00:53:45
【问题描述】:
- 问题末尾有一个更新。现在我必须在一个小项目中通过一行更改来打开和关闭错误,所有代码都转录在下面。
- Alexey Romanov 的答案非常出色。检查问题的最后。这是 Android Studio 环境的一个惊人而未知的功能。
我在使用更新的 Android 3.4.2 的 Kotlin 中发现了一个非常古怪的错误。
首先,我使用我唯一模块中的任何 kotlin 文件中的主模块在我的计算机(不是 Android)中运行我的测试代码。它总是对我有用,但它已经开始给出我在下面评论的错误,然后是另一个不允许运行主模块的错误。
在Stack Overflow 中搜索,一位用户声称最后描述的错误在使用java 文件夹下的test 文件时结束(不是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")
}
我只是指向 test 文件中的fun main() 行,然后单击绿色图标。
错误信息
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")
}
当我在我的电脑(不是 Android)中运行 test.kt 代码时的完整错误消息:
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
Alexey Romanov 一针见血!
我进行了更多研究,发现 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
并将初始化放在其他地方(例如,在 MainActivity 类中的 onCreate 内。在我的情况下,就在第一次调用 addSplit 之前,这是来自 TimingLogger 类的方法之一
timings = TimingLogger("MyTag", "Your")
现在我的测试代码会打印出来
start
fool
what a big fool
ok
【问题讨论】:
-
你是如何实例化 vDispFu 的?
-
抱歉,又一个错字。简化使用
vCl。 -
我已经更正了。
-
我刚刚在我的测试文件中尝试过这个,它通过了。您是否将它们放在同一个文件中?
-
可以在这里发布完整代码吗?