shubham_ag
shubham_ag

Reputation: 43

@Inject for Hilt is giving UninitializedPropertyAccessException

I am using Hilt in my project, and it is working fine everywhere apart from this one file.

abstract class SomeFile {
  
    @Inject
    lateinit var useCase: UseCase

    fun setData() {
       if (useCase.driver == 1){ do something }
       else { do something }
    }
}

This same "UseCase" inject is working in another files like viewmodel and activity. But only in this abstract class file is where I am getting this exception. What could be the issue here?

Module class

@Module
@InstallIn(SingletonComponent::class)
object HiltUseModule {
    @Provides
    @Singleton
    fun getUseCase(stateMachine: StateMachine): UseCase {
        return createProxyInstance(stateMachine)
    }
}

The app doesn't crash or anything. It just goes to the if condition and doesn't do anything. I used debug to check what is the value of 'useCase' there, and it shows the exception UninitializedPropertyAccessException.

Thanks in advance.

Upvotes: 1

Views: 1415

Answers (4)

johngray1965
johngray1965

Reputation: 652

You need to pass the dependency in as a parameter. You can make it a @Inject constructor. Or have whatever is creating it pass it in.

abstract class SomeFile @Inject constructor(val useCase: UseCase){

    fun setData() {
       if (useCase.driver == 1){ do something }
       else { do something }
    }
}

Upvotes: 0

Ganesh Pokale
Ganesh Pokale

Reputation: 1594

Inject dependencies in classes not supported by Hilt

If you need to perform field injection in classes that Hilt doesn't support.

you need to use @EntryPoint annotation

  @EntryPoint
  @InstallIn(SingletonComponent::class)
  interface MyEntryPoint {
    fun getUseCase(): UseCase
  }
  

and access user class using

val hiltEntryPoint = EntryPointAccessors.fromApplication(appContext,MyEntryPoint::class.java)
val useCase = hiltEntryPoint.getUseCase()

Upvotes: -1

Kevin Coppock
Kevin Coppock

Reputation: 134664

Rather than field injection, you should use constructor injection to acquire an instance of SomeFile.

class SomeFile @Inject internal constructor(private val useCase: UseCase) {
  fun setData() {
    if (useCase.driver == 1){ do something }
      else { do something }
    }
  }
}

Then, you will need to inject this into some component which is an entry point (whether that's your ViewModel, Fragment, or Activity:

@AndroidEntryPoint(AppCompatActivity::class)
class MyActivity : Hilt_AppCompatActivity() {
  @Inject internal lateinit var someFile: SomeFile

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    someFile.setData()
  }
}

Upvotes: 2

Karan Mehta
Karan Mehta

Reputation: 1541

Try this :

abstract class SomeFile {
 
    fun setData(useCase : UseCase) {
       if (useCase.driver == 1){ do something }
       else { do something }
    }
}

What it does is that the parameter that you pass in function will find object of UseCase from wherever it can.

Upvotes: 0

Related Questions