0

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.

  • 1
    Can you show the whole stack trace? One thing you can try is setting breakpoints on the line where you assign the property and the line where it's crashing. See if lifecycle methods are getting called in the order you expect. I'm kind of stumped from what I see. – Tenfour04 Jan 17 '23 at 18:19
  • I tried to reproduce the error after leaving it alone for an hour. It works fine now, I guess the right way about it is to take a break. Will take this one down later. – George Kotzabassis Jan 17 '23 at 18:48

0 Answers0