当前位置: 首页 > 知识库问答 >
问题:

静态编程语言中如何初始化用于对象表达式的lateinit变量?

陶树
2023-03-14

这不是重复。“object”表达式是关键字。

我正在尝试将Timber Android库与 https://github.com/orhanobut/logger 集成,我需要一个自定义的LogStrategyTimber来满足我的需求。

我想出了这个逻辑。但是我在初始化自定义日志策略时遇到了困难

class App : Application() {
    // I CREATED THE lateinit VARIABLE
    lateinit var customLogStrategyForTimber: LogStrategy
    
    override fun onCreate() {
        super.onCreate()
        Timber.plant(object : Timber.DebugTree() {
            override fun log(
                priorityTimber: Int, tagTimber: String?, message: String, t: Throwable?
            ) {
                
                // USED THE lateinit HERE
                customLogStrategyForTimber = object : LogcatLogStrategy() {
                    override fun log(priority: Int, tag: String?, message: String) {
                        super.log(priorityTimber, tagTimber, message)
                    }
                }

 println("customLogStrategyForTimber: ${::customLogStrategyForTimber.isInitialized}") // PRINTS TRUE
            }
        })

        println("customLogStrategyForTimber OUTSIDE: ${::customLogStrategyForTimber.isInitialized}") // PRINTS FALSE - WHY??


            var formatStrategy1 = PrettyFormatStrategy.newBuilder()
                
                // TRYING TO CALL THE lateinit VARIABLE HERE
                // NOW, HERE THE lateinit IS NOT INITIALIZED.
                .logStrategy(customLogStrategyForTimber)
                .build()
            Logger.addLogAdapter(AndroidLogAdapter(formatStrategy1))
    }
}

customLogStrategyForTimber从未初始化。有更好的方法来实现这个逻辑吗?尝试在第一个override fun log方法中添加整个formatStrategy代码会导致使用Timber logging时出现意外行为,因此这似乎不是一个容易的选择。

  Caused by: kotlin.UninitializedPropertyAccessException: lateinit property customLogStrategyForTimber has not been initialized

里面的代码永远不会运行。

已创建示例项目:https://github.com/shipsywor/demotimberlogger

我在上面的代码中添加了println语句。您将看到::customLogStrategyForTimber。isInitialized在代码的某一点返回False,在另一点返回True

注意:我不能将formatStrategy代码放在Timber中。植物{…}。这会导致意外行为。


共有3个答案

吕晟睿
2023-03-14

让我向你解释一下。木材是一种线程,需要一些时间才能完成其工作。你的代码,你在日志中得到假,它突然在Timber.plan之后运行并打印假,同时Timper.plan线程正在执行并行和初始化的变量,然后打印你得到真的地方。

你应该这样做:

     class App : Application() {
 
    lateinit var customLogStrategyForTimber: LogStrategy
 
    override fun onCreate() {
        super.onCreate()
 
        Timber.plant(object : Timber.DebugTree() {
 
            override fun log(
                priorityTimber: Int, tagTimber: String?, message: String, t: Throwable?
            ) {
                customLogStrategyForTimber = object : LogcatLogStrategy() {
                    override fun log(priority: Int, tag: String?, message: String) {
                        super.log(priorityTimber, "global_tag_$tagTimber", message)
                    }
                }
                    Logger.d(message)
            }
        })
 
 
        thread {
            val formatStrategy: FormatStrategy = PrettyFormatStrategy.newBuilder()
                .showThreadInfo(false)
                .methodCount(1)
                .methodOffset(5)
                .logStrategy(customLogStrategyForTimber)
                .build()
 
            Logger.addLogAdapter(AndroidLogAdapter(formatStrategy))
 
            println("global_tag INSIDE thread: ${::customLogStrategyForTimber.isInitialized}")
 
        }
 
        Timber.d("Initialize Timber")
    }
}
麹正业
2023-03-14

初始化< code>lateinit var的代码位于您现场创建的< code>DebugTree实现的< code>log()中。在这里调用< code>Timber.plant()时不会执行它,您只是用一些实现注册了< code>DebugTree的一个实例。

因此,当您使用“外部”到达 println 时,该日志方法从未被调用过,因此自定义日志策略尚未初始化。

於乐语
2023-03-14
匿名用户

看起来您已经不必要地创建了一个本地价值自定义LogStrategyForTimber,该自定义只能在 Timber.plant() 方法中访问。实际上,您并没有真正使用您在类顶部声明的 lateinit var。如果您刚刚从 Timber.plant() 方法中的对象声明中删除了 val,则代码将按预期工作。

现在,您声明的对象停留在< code>Timber.plant()方法内部,不能从外部访问。

 类似资料:
  • 因为我是android开发新手,所以我不知道如何在使用lateinit变量之前初始化它。在此之前,我尝试过执行,就像这个github中提到的,但没有成功。所以现在我希望问题出在初始化textInput变量上。

  • 问题内容: 我有以下代码: 这给了我以下错误: 解析错误:语法错误,在第19行的/home/user/Sites/site/registration/inc/registration.class.inc中出现意外的’(’,期待’)’ 所以,我想我做错了什么…但是如果不那样做怎么办?如果我用常规字符串更改mktime内容,它将起作用。所以,我知道我能做到这一点 的那种 像.. 有人有指针吗? 问题答

  • 是否有可能在Kotlin 属性初始化之前从其获取< code>::class.java? 从逻辑上讲,它应该可以工作——我试图获取一个类而不是一个值,但实际上它在未初始化的属性访问异常时失败。 请注意,我试图获取类的属性位于泛型类中,其类型是泛型参数之一: 我需要这个类来创建的实例 当然,我不能做到: 对此有什么解决办法吗?

  • 问题内容: 我想知道为什么默认情况下C,C ++和Java中的确切静态变量初始化为零?为什么对局部变量不是这样? 问题答案: 为什么要对静态变量进行确定性初始化而对局部变量不进行初始化? 了解如何实现静态变量。 它们的内存在链接时分配,并且它们的初始值也在链接时提供。 没有运行时开销。 另一方面,用于局部变量的内存是在运行时分配的。堆栈必须增长。你不知道以前在那里。如果需要,可以清除该内存(将其清

  • 我正在将一个项目从java迁移到kotlin,该项目使用了许多可能为空的变量,并且在与用户或外部作业进行一些交互之前不会初始化它们。 我试图使用kotlin null安全优势,并且我试图避免在源代码中使用<code>nulllateinitvar location:location?=空 我这样做是为了避免使用< code >?每次我需要使用这些变量时。现在的问题是...如果变量没有初始化会发生什

  • 我正在尝试创建一个字典过滤器来过滤传入的参数列表。 问题是,当列表中有应该过滤和删除的参数时-我得到一个NullPointerExc的。 基本信息: 这是过滤器的外观: 过滤器示例: 过滤列表(<code>列表 列表示例