hope you are well.
I am writing to find more strategies to debugging View Binding in Kotlin. For context, I am progressing through the following course on Udemy. I am currently stuck on module 142. The content pertains to creating a custom toolbar for a given activity.
Before showing the associated code, here are the Gradle Files.
Project:Gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.3.1' apply false
id 'com.android.library' version '7.3.1' apply false
id 'org.jetbrains.kotlin.android' version '1.7.20' apply false
}
Module:Gradle
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
namespace //anonymized package name
compileSdk 33
defaultConfig {
applicationId //anonymized package name
minSdk 21
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures{
viewBinding true
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.0'
implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}
The Main Activity is very simple - its only interactive element is a button that launches another activity, so I will show the activity it launches. The destination activity is the only other activity in the project so far. The problem occurs early on.
Activity Class
package anonymized package name
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import /*anonymized package name*/.databinding.ActivityExerciseBinding
class ExerciseActivity : AppCompatActivity() {
private lateinit var bindExercise:ActivityExerciseBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
bindExercise = ActivityExerciseBinding.inflate(layoutInflater)
val view = bindExercise.root
setContentView(view)
setSupportActionBar(bindExercise.toolbarExercise).apply {
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_back_btn)
supportActionBar?.show()
}
bindExercise.toolbarExercise.setNavigationOnClickListener{
onBackPressedDispatcher.onBackPressed()
}
}
override fun onStart() {
super.onStart()
Log.i("TAG_BIND","$bindExercise")
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menus, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when(item.itemId){
R.id.action_back -> {onBackPressedDispatcher.onBackPressed(); return true}
else -> super.onOptionsItemSelected(item)
}
}
}
Activity Layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ExerciseActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbarExercise"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:theme="@style/ToolbarTheme"
tools:text="label here" />
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:layout_below="@id/toolbarExercise"
android:textSize="22sp"/>
</RelativeLayout>
Theme in Reference
<resources>
<--! ... -->
<style name="ToolbarTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<item name="android:textColor">@color/toolbar_color_control_normal</item>
<item name="android:background">@color/teal_200</item>
<item name="android:text">@string/app_name</item>
</style>
</resources>
The error is simple. At this line of code in the ExerciseActivity.OnStart() method, the line of code that writes to the log, produces this error:
// Line of Code
Log.i("TAG_BIND","$bindExercise")
// Resulting Error at Runtime
kotlin.UninitializedPropertyAccessException: lateinit property bindExercise has not been initialized
Rather, it seems to me that bindExercise is never initialized, even though it is the second line of code in the onCreate() method.
I have tried each of the following strategies to overcome the error:
- Refactor Activity Name (Class and Layout)
- Invalidate Caches: Clear VCS Caches and Indexes, File System and Local History
- Restart IDE
- Create New Empty Activity and Map Methods/Properties Manually
- Update Module:Gradle implementation androidx:appcompat from 1.5.1 to 1.6.0
The only thing I have not tried is destroying the project and starting from scratch. This seems like a terrible practice in general; starting over like that is like crumbling up an acceptable report because your auditor can't distinguish the kerning on your choice font.
Does anyone have any suggestions on how to debug this?
Thank you.