Search code examples
androidkotlindependency-injectiondagger-2

kotlin.Unit cannot be cast to "Class" Dagger 2 in Android Kotlin


I am developing an Android app using Kotlin. I am trying to understand how Dagger 2 works to perform dependency injection. I am very new to Dagger 2. I am following this tutorial,https://medium.com/@elye.project/dagger-2-for-dummies-in-kotlin-with-one-page-simple-code-project-618a5f9f2fe8 to understand how it works and applying it to my project too. But I am getting an error. Following is what I have done so far.

I created an interface called AppComponent with the following code

package com.example.utils

import com.example.memento.LoginActivity
import dagger.Component

@Component
interface AppComponent
{
    fun inject(app: LoginActivity)
}

I also created a class called AuthService with the following code.

package com.example.services

import javax.inject.Inject

class AuthService @Inject constructor()
{
    public fun login(): String
    {
        return "I am logged in";
    }
}

This is my LoginActivity class

class LoginActivity : AppCompatActivity()
{
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        val authService = DaggerAppComponent.create().inject(this) as AuthService
        tv_testing.text = authService.login();
    }
}

When I run my app, I get the following error

java.lang.ClassCastException: kotlin.Unit cannot be cast to com.example.services.AuthService
at com.example.memento.LoginActivity.onCreate(LoginActivity.kt:25)
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at androidx.test.runner.MonitoringInstrumentation.callActivityOnCreate(MonitoringInstrumentation.java:674)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

E/MonitoringInstr: Exception encountered by: com.example.memento.LoginActivity@39cc00e. Dumping thread state to outputs and pining for the fjords.
    java.lang.ClassCastException: kotlin.Unit cannot be cast to com.example.services.AuthService
        at com.example.memento.LoginActivity.onCreate(LoginActivity.kt:25)
        at android.app.Activity.performCreate(Activity.java:7136)
        at android.app.Activity.performCreate(Activity.java:7127)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at androidx.test.runner.MonitoringInstrumentation.callActivityOnCreate(MonitoringInstrumentation.java:674)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
E/THREAD_STATE:   Thread[MonitoringInstrumentation,5,main]
        java.lang.Object.wait(Native Method)
        android.app.Instrumentation.startActivitySync(Instrumentation.java:496)
        android.app.Instrumentation.startActivitySync(Instrumentation.java:435)
        androidx.test.runner.MonitoringInstrumentation.access$101(MonitoringInstrumentation.java:98)
        androidx.test.runner.MonitoringInstrumentation$4.call(MonitoringInstrumentation.java:443)
        androidx.test.runner.MonitoringInstrumentation$4.call(MonitoringInstrumentation.java:440)
        java.util.concurrent.FutureTask.run(FutureTask.java:266)
        java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        java.lang.Thread.run(Thread.java:764)

      Thread[Binder:11719_2,5,main]

      Thread[magnifier pixel copy result handler,5,main]
        android.os.MessageQueue.nativePollOnce(Native Method)
        android.os.MessageQueue.next(MessageQueue.java:326)
        android.os.Looper.loop(Looper.java:160)
        android.os.HandlerThread.run(HandlerThread.java:65)

      Thread[FinalizerWatchdogDaemon,5,system]
        java.lang.Object.wait(Native Method)
        java.lang.Daemons$FinalizerWatchdogDaemon.sleepUntilNeeded(Daemons.java:297)
        java.lang.Daemons$FinalizerWatchdogDaemon.runInternal(Daemons.java:277)
        java.lang.Daemons$Daemon.run(Daemons.java:103)
        java.lang.Thread.run(Thread.java:764)

      Thread[InstrumentationConnectionThread,5,main]
        android.os.MessageQueue.nativePollOnce(Native Method)
        android.os.MessageQueue.next(MessageQueue.java:326)
        android.os.Looper.loop(Looper.java:160)
        android.os.HandlerThread.run(HandlerThread.java:65)

      Thread[Profile Saver,5,system]

      Thread[main,5,main]
        dalvik.system.VMStack.getThreadStackTrace(Native Method)
        java.lang.Thread.getStackTrace(Thread.java:1538)
        java.lang.Thread.getAllStackTraces(Thread.java:1588)
        androidx.test.runner.MonitoringInstrumentation.getThreadState(MonitoringInstrumentation.java:643)
        androidx.test.runner.MonitoringInstrumentation.dumpThreadStateToOutputs(MonitoringInstrumentation.java:638)
        androidx.test.runner.MonitoringInstrumentation.onException(MonitoringInstrumentation.java:632)
        androidx.test.runner.AndroidJUnitRunner.onException(AndroidJUnitRunner.java:522)
        android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2910)
        android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        android.os.Handler.dispatchMessage(Handler.java:106)
        android.os.Looper.loop(Looper.java:193)
        android.app.ActivityThread.main(ActivityThread.java:6669)
        java.lang.reflect.Method.invoke(Native Method)
        com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

      Thread[Binder:11719_1,5,main]

      Thread[ReferenceQueueDaemon,5,system]
        java.lang.Object.wait(Native Method)
        java.lang.Daemons$ReferenceQueueDaemon.runInternal(Daemons.java:178)
        java.lang.Daemons$Daemon.run(Daemons.java:103)
        java.lang.Thread.run(Thread.java:764)

      Thread[Jit thread pool worker thread 0,5,main]

      Thread[FinalizerDaemon,5,system]
        java.lang.Object.wait(Native Method)
        java.lang.Object.wait(Object.java:422)
        java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:188)
        java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:209)
        java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:232)
        java.lang.Daemons$Daemon.run(Daemons.java:103)
        java.lang.Thread.run(Thread.java:764)

      Thread[HeapTaskDaemon,5,system]

      Thread[Instr: com.example.memento.MockTestRunner,5,main]
        java.lang.Object.w
E/MonitoringInstr: Dying now...
D/AndroidRuntime: Shutting down VM


    --------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.memento, PID: 11719
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.memento/com.example.memento.LoginActivity}: java.lang.ClassCastException: kotlin.Unit cannot be cast to com.example.services.AuthService
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: java.lang.ClassCastException: kotlin.Unit cannot be cast to com.example.services.AuthService
        at com.example.memento.LoginActivity.onCreate(LoginActivity.kt:25)
        at android.app.Activity.performCreate(Activity.java:7136)
        at android.app.Activity.performCreate(Activity.java:7127)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at androidx.test.runner.MonitoringInstrumentation.callActivityOnCreate(MonitoringInstrumentation.java:674)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.app.ActivityThread.main(ActivityThread.java:6669) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 
E/MonitoringInstr: Exception encountered by: Thread[main,5,main]. Dumping thread state to outputs and pining for the fjords.
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.memento/com.example.memento.LoginActivity}: java.lang.ClassCastException: kotlin.Unit cannot be cast to com.example.services.AuthService
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: java.lang.ClassCastException: kotlin.Unit cannot be cast to com.example.services.AuthService
        at com.example.memento.LoginActivity.onCreate(LoginActivity.kt:25)
        at android.app.Activity.performCreate(Activity.java:7136)
        at android.app.Activity.performCreate(Activity.java:7127)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at androidx.test.runner.MonitoringInstrumentation.callActivityOnCreate(MonitoringInstrumentation.java:674)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.app.ActivityThread.main(ActivityThread.java:6669) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 
E/THREAD_STATE:   Thread[MonitoringInstrumentation,5,main]
        java.lang.Object.wait(Native Method)
        android.app.Instrumentation.startActivitySync(Instrumentation.java:496)
        android.app.Instrumentation.startActivitySync(Instrumentation.java:435)
        androidx.test.runner.MonitoringInstrumentation.access$101(MonitoringInstrumentation.java:98)
        androidx.test.runner.MonitoringInstrumentation$4.call(MonitoringInstrumentation.java:443)
        androidx.test.runner.MonitoringInstrumentation$4.call(MonitoringInstrumentation.java:440)
        java.util.concurrent.FutureTask.run(FutureTask.java:266)
        java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        java.lang.Thread.run(Thread.java:764)

      Thread[Binder:11719_2,5,main]

      Thread[magnifier pixel copy result handler,5,main]
        android.os.MessageQueue.nativePollOnce(Native Method)
        android.os.MessageQueue.next(MessageQueue.java:326)
        android.os.Looper.loop(Looper.java:160)
        android.os.HandlerThread.run(HandlerThread.java:65)

      Thread[FinalizerWatchdogDaemon,5,system]
        java.lang.Object.wait(Native Method)
        java.lang.Daemons$FinalizerWatchdogDaemon.sleepUntilNeeded(Daemons.java:297)
        java.lang.Daemons$FinalizerWatchdogDaemon.runInternal(Daemons.java:277)
        java.lang.Daemons$Daemon.run(Daemons.java:103)
        java.lang.Thread.run(Thread.java:764)

      Thread[InstrumentationConnectionThread,5,main]
        android.os.MessageQueue.nativePollOnce(Native Method)
        android.os.MessageQueue.next(MessageQueue.java:326)
        android.os.Looper.loop(Looper.java:160)
        android.os.HandlerThread.run(HandlerThread.java:65)

      Thread[Profile Saver,5,system]

      Thread[main,5,main]
        dalvik.system.VMStack.getThreadStackTrace(Native Method)
        java.lang.Thread.getStackTrace(Thread.java:1538)
        java.lang.Thread.getAllStackTraces(Thread.java:1588)
        androidx.test.runner.MonitoringInstrumentation.getThreadState(MonitoringInstrumentation.java:643)
        androidx.test.runner.MonitoringInstrumentation.dumpThreadStateToOutputs(MonitoringInstrumentation.java:638)
        androidx.test.runner.MonitoringInstrumentation.onException(MonitoringInstrumentation.java:632)
        androidx.test.runner.AndroidJUnitRunner.onException(AndroidJUnitRunner.java:522)
        androidx.test.runner.MonitoringInstrumentation$3.uncaughtException(MonitoringInstrumentation.java:268)
        java.lang.Thread.dispatchUncaughtException(Thread.java:1955)

      Thread[Binder:11719_1,5,main]

      Thread[ReferenceQueueDaemon,5,system]
        java.lang.Object.wait(Native Method)
        java.lang.Daemons$ReferenceQueueDaemon.runInternal(Daemons.java:178)
        java.lang.Daemons$Daemon.run(Daemons.java:103)
        java.lang.Thread.run(Thread.java:764)

      Thread[Jit thread pool worker thread 0,5,main]

      Thread[FinalizerDaemon,5,system]
        java.lang.Object.wait(Native Method)
        java.lang.Object.wait(Object.java:422)
        java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:188)
        java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:209)
        java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:232)
        java.lang.Daemons$Daemon.run(Daemons.java:103)
        java.lang.Thread.run(Thread.java:764)

      Thread[HeapTaskDaemon,5,system]

      Thread[Instr: com.example.memento.MockTestRunner,5,main]
        java.lang.Object.wait(Native Method)
        java.lang.Thread.parkFor$(Thread.java:2137)
        sun.misc.Unsafe.park(Unsafe.java:358)
        java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:230)
        java.util.concurrent.FutureTask.awaitDone(FutureTask.java:447)
        java.util.concurrent.FutureTask.get(FutureTask.java:205)
        androidx.test.runner.MonitoringInstrumentation.startActivitySync(MonitoringInstrumentation.java:448)
        androidx.test.rule.ActivityTestRule.launchActivity(ActivityTestRule.java:354)
        androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:525)
        org.junit.rules.RunRules.evaluate(RunRules.java:20)
        org.junit.runners.ParentRunner.runLeaf(ParentRunner
E/MonitoringInstr: Dying now...
W/MonitoringInstr: Invoking uncaught exception handler java.lang.ThreadGroup[name=main,maxpri=10] (a class java.lang.ThreadGroup)
I/Process: Sending signal. PID: 11719 SIG: 9
Test running failed: Instrumentation run failed due to 'Process crashed.'

What is wrong with my code?

I tried updating the LoginActivity to this

class LoginActivity : AppCompatActivity()
{
    lateinit var authService: AuthService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        DaggerAppComponent.create().inject(this)
        tv_testing.text = authService.login()
    }
}

Then I got this error

kotlin.UninitializedPropertyAccessException: lateinit property authService has not been initialized
at com.example.memento.LoginActivity.onCreate(LoginActivity.kt:27)

Solution

  • DaggerAppComponent.create().inject(this) doesn't return anything but you're trying to cast it to AuthService. Therefore, you get ClassCastException. Instead, you should first declare AuthService as lateinit var and annotate it with @Inject. Then you can call inject() function. You can see full code below:

    class LoginActivity : AppCompatActivity()
    {
        @Inject
        private lateinit var authService: AuthService
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_login)
            DaggerAppComponent.create().inject(this)
            tv_testing.text = authService.login();
        }
    }
    

    I hope my answer helps.