SingletonInstance 从未被设置?

问题描述 投票:0回答:1

我收到以下错误消息:

FATAL EXCEPTION: main
    Process: com.example.myapp.debug, PID: 27111
    java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:583)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1049)
    Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:573)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1049)
    Caused by: com.example.ConfException: ... is NULL!
        at com.example.SingletonInstance.getInstance(SingletonInstance.kt:21)
        at com.example.ServiceClientCtxConf$Companion.getInstance(Unknown Source:2)
        at com.example.AppClientConf$Companion.setConf(AppClientConf.kt:52)
        at com.example.activities.MyActivity.onCreate(MyActivity.kt:200)
        ...

MyActivity
开始,我在提到的第 200 行进行 REST 调用:

AppClientConf
    .setConf() // line 200
    .doOnNext { successful ->
        //
    }
    .subscribe()

而这是

AppClientConf
简化后的样子(上面的错误消息行):

class AppClientConf private constructor() {

    companion object {

        fun setConf(): Observable<Boolean> = 
            ServiceClientConf
                .setConf(context = ServiceClientCtxConf.instance) // line 52
                .onErrorReturnItem(false)
    }
}

由于抛出的

ConfException: ... is NULL!
在错误日志中,
ServiceClientCtxConf.instance
似乎是
null
以及进一步提到的
ServiceClientCtxConf
:

class ServiceClientCtxConf(
    val serviceClient: IServiceClient = ServiceClient()
) {

    companion object : ISingletonInstance<ServiceClientCtxConf> by SingletonInstance()
}

有了这个

SingletonInstance

interface ISingletonInstance<T> {

    var instance: T
}

class SingletonInstance<T> : ISingletonInstance<T> {

    private var singletonInstance: T? = null

    override var instance: T
        set(value) {
            singletonInstance = value
        }
        get() = singletonInstance ?: throw ConfException("... is NULL!") // get is here line 21
}

SingletonInstance::set()
是否从未被
ServiceClientCtxConf.instance
隐式调用?

我在这里缺少什么?

kotlin singleton
1个回答
0
投票

没有人调用

SingletonInstance#instance#set
方法。

首先,Kotlin 中的属性只是一个类字段,提供了 setter 和 getter。如果属性具有非基本类型,则其默认初始化值为 null。

其次,

companion object
是一个单例,并且在第一次调用时延迟初始化。当其类型是接口时,必须提供实现。这就是
provided by
功能发挥作用的地方。在您的案例中,实现由
SingletonInstance()
提供。

最后,当调用

.setConf(context = ServiceClientCtxConf.instance)
时,它会转换为
ServiceClientCtxConf.Companion.instance
并执行getter。由于没有通过
set
提供任何值,因此返回默认值。

使用

companion object
进行构造不会隐式调用
set
方法。此外,作为一个单身人士,它甚至没有对
ServiceClientCtxConf
的引用。

要解决此问题,需要显式将

ServiceClientCtxConf
设置为
Companion.instance

© www.soinside.com 2019 - 2024. All rights reserved.