I get the error
java.lang.IllegalStateException: instance not initialized
you can test it at https://www.dropbox.com/s/gxeok1fyttsl54u/MyMirror.zip?dl=0
It seems that the code operator fun getValue(thisRef: Any?, property: KProperty<*>)... in UIApp causes the error.
But the code is from a sample code, I hardly don't change, you can see source code at https://github.com/antoniolg/Kotlin-for-Android-Developers/blob/master/app/src/main/java/com/antonioleiva/weatherapp/ui/App.kt
and
Why?
java.lang.RuntimeException: Unable to start activity ComponentInfo{info.dodata.mirror/ui.UIMain}: java.lang.IllegalStateException: instance not initialized
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2107)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2132)
at android.app.ActivityThread.access$700(ActivityThread.java:140)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1238)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4918)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:994)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:761)
at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.IllegalStateException: instance not initialized
at ui.UIApp$NotNullSingleValueVar.getValue(UIApp.kt:23)
at ui.UIApp$Companion.getInstance(UIApp.kt)
at dal.DBSettingHelper.<init>(DBSettingHelper.kt:9)
at ui.UIMain.onCreate(UIMain.kt:14)
at android.app.Activity.performCreate(Activity.java:5185)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2071)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2132)?
at android.app.ActivityThread.access$700(ActivityThread.java:140)?
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1238)?
at android.os.Handler.dispatchMessage(Handler.java:99)?
at android.os.Looper.loop(Looper.java:137)?
at android.app.ActivityThread.main(ActivityThread.java:4918)?
at java.lang.reflect.Method.invokeNative(Native Method)?
at java.lang.reflect.Method.invoke(Method.java:511)?
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:994)?
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:761)?
at dalvik.system.NativeStart.main(Native Method)?
UIMain
package ui
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import dal.DBSettingHelper
import info.dodata.mirror.R
class UIMain : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.layout_main)
var ss= DBSettingHelper();
}
}
DBSettingHelper
package dal
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import org.jetbrains.anko.db.*
import ui.UIApp
object DBSettingTable {
val TableNAME = "SettingTable"
val _ID = "_id"
val Name = "name"
val CreatedDate = "createdDate"
val Description="description"
}
class DBSettingHelper(mContext: Context = UIApp.instance) : ManagedSQLiteOpenHelper(
mContext,
DB_NAME,
null,
DB_VERSION) {
companion object {
val DB_NAME = "setting.db"
val DB_VERSION = 1
val instance by lazy { DBSettingHelper() }
}
override fun onCreate(db: SQLiteDatabase) {
db.createTable( DBSettingTable.TableNAME , true,
DBSettingTable._ID to INTEGER + PRIMARY_KEY,
DBSettingTable.Name to TEXT,
DBSettingTable.CreatedDate to INTEGER,
DBSettingTable.Description to TEXT
)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.dropTable(DBSettingTable.TableNAME, true)
onCreate(db)
}
}
UIApp
package ui
import android.app.Application
import kotlin.reflect.KProperty
class UIApp : Application() {
companion object {
var instance: UIApp by NotNullSingleValueVar()
}
override fun onCreate() {
super.onCreate()
instance = this
}
class NotNullSingleValueVar<T> {
private var value: T? = null
operator fun getValue(thisRef: Any?, property: KProperty<*>): T =
value ?: throw IllegalStateException("${property.name} not initialized")
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this.value = if (this.value == null) value
else throw IllegalStateException("${property.name} already initialized")
}
}
onCreate function in UIApp class is never called and thus an instance of UIApp is never initialized. This is happening because you didn't add UIApp class to AndroidManifest and because of that your app did not realize that you have your custom Application class in a project.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="info.dodata.mirror">
<application
<!--Add line bellow to your manifest file and app will work just fine-->
android:name="ui.UIApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name="ui.UIMain">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>