Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

lateinit property has not been initialized

I have a custom linearlayout class and when I want to create instance of this class, I get the following error:
lateinit property has not been initialized

I'm using the latest version of butterknife library.

The following is my Kotlin class:

class MenuItemView : LinearLayout {  @BindView(R.id.menu_title_text_view_id) lateinit var menuTitleTextView : CTextBasic  constructor(ctx: Context) : super(ctx) { }  init {     val view = LayoutInflater.from(context).inflate(R.layout.menu_item,this)     ButterKnife.bind(this,view) }  constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) {     val menuAttrs = context.theme.obtainStyledAttributes(attrs, R.styleable.MenuItemView, 0, 0)     try {         val title: String = menuAttrs.getString(R.styleable.MenuItemView_menu_title)         menuTitleTextView.text = title     }catch (e : Exception){         e.printStackTrace()     }finally {         menuAttrs.recycle()     } } fun setTitle( title : String){     menuTitleTextView.text = title } } 

Error Log

kotlin.UninitializedPropertyAccessException: lateinit property menuTitleTextView has not been initialized at com.leavigstone.liberali.ui.custom.menu.MenuItemView.setTitle(MenuItemView.kt:48) at com.leavigstone.liberali.ui.activities.MainActivity.onAddButtonClick(MainActivity.java:142) at com.leavigstone.liberali.ui.activities.MainActivity_ViewBinding$3.doClick(MainActivity_ViewBinding.java:54) at butterknife.internal.DebouncingOnClickListener.onClick(DebouncingOnClickListener.java:22) at android.view.View.performClick(View.java:4780) at android.view.View$PerformClick.run(View.java:19866) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5254) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) 
like image 656
Jemo Mgebrishvili Avatar asked Oct 21 '16 11:10

Jemo Mgebrishvili


People also ask

What if Lateinit is not initialized?

If you try accessing Lateinit variables without initializing, it will throw an exception stating that it is not initialized or properly being accessed.

How do you initialize a Lateinit property?

In order to create a "lateInit" variable, we just need to add the keyword "lateInit" as an access modifier of that variable. Following are a set of conditions that need to be followed in order to use "lateInit" in Kotlin. Use "lateInit" with a mutable variable. That means, we need to use "var" keyword with "lateInit".

How do I know if Lateinit property is initialized?

Along with this modifier, Kotlin provides a couple of methods to check whether this variable is initialized or not. Use "lateInit" with a mutable variable. That means, we need use "var" keyword with "lateInit". "lateInit" is only allowed with non-NULLable data types.

How do you initialize Lateinit in Kotlin?

Kotlin lateinit – To declare non null Kotlin Variables without initialization, use lateinit keyword during declaration of the variable. Initialization of that variable could be done at a later point in code. Note : lateinit is supported from Kotlin 1.2. Make sure you are updated to latest Kotlin.


2 Answers

If you don't want to use any thirdparty libraries, you can add these extension functions (I tend to have a ContextExtensions.kt or ViewExtensions.kt for Context or View related extension functions), then put in it

inline fun <reified T : View> View.find(id: Int): T = findViewById(id) as T inline fun <reified T : View> Activity.find(id: Int): T = findViewById(id) as T inline fun <reified T : View> Fragment.find(id: Int): T = view?.findViewById(id) as T 

these let you call find from within Activity, Fragment, and Views. So inside your class instead of

@BindView(R.id.menu_title_text_view_id) lateinit var menuTitleTextView : CTextBasic 

you can have

val menuTitleTextView by lazy { find<CTextBasic>(R.id.menu_title_text_view_id) } 

For things like UIs, it's better to val instead of var when they don't need to change. As a general rule in programming, try to keep things as immutable as possible, you would get far less bugs.

like image 56
Billy Avatar answered Oct 01 '22 12:10

Billy


I found this works for me.

Change your build.gradle in your project app module.

dependencies {     compile "com.jakewharton:butterknife:8.8.1"     kapt "com.jakewharton:butterknife-compiler:8.8.1" } 

use kapt instead of annotationProcessor.

and then you can do your familiar ButterKnife annotation like this:

class MainActivity : AppCompatActivity() {      @BindView(R.id.myButton)     lateinit var myButton: Button      override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         setContentView(R.layout.activity_main)         ButterKnife.bind(this)         //...     } } 

Enjoy.

like image 39
Johnny Avatar answered Oct 01 '22 12:10

Johnny