I get following error message:
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)
...
Starting from the MyActivity
, I make a REST call at mentioned line 200:
AppClientConf
.setConf() // line 200
.doOnNext { successful ->
//
}
.subscribe()
whereas this is the AppClientConf
simplified is like (upper error message line):
class AppClientConf private constructor() {
companion object {
fun setConf(): Observable<Boolean> =
ServiceClientConf
.setConf(context = ServiceClientCtxConf.instance) // line 52
.onErrorReturnItem(false)
}
}
As the thrown ConfException: ... is NULL!
is on the error log, the ServiceClientCtxConf.instance
seem to be null
and further the mentioned ServiceClientCtxConf
:
class ServiceClientCtxConf(
val serviceClient: IServiceClient = ServiceClient()
) {
companion object : ISingletonInstance<ServiceClientCtxConf> by SingletonInstance()
}
with this 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
}
Is the SingletonInstance::set()
never being called implicitly by ServiceClientCtxConf.instance
?
What am I missing here?
Nobody calls SingletonInstance#instance#set
method.
First, property in Kotlin is just a class field with setter and getter provided. If property has non-primitive type its default initialization value is null.
Second, companion object
is a singleton and lazily initialized at the first call. When its type is an interface then an implementation must be provided. That's where provided by
feature comes into play. In your case implementation provided by SingletonInstance()
.
Last, when .setConf(context = ServiceClientCtxConf.instance)
is called then it is converted to ServiceClientCtxConf.Companion.instance
and getter is executed. Since no value provided via set
then default is returned.
Construction with companion object
does not call set
method implicitly. Moreover being a singleton it doesn't have even a reference to ServiceClientCtxConf
.
To fix that need to explicitly set ServiceClientCtxConf
to Companion.instance
.