@AssistedInject in ViewModel using Dagger (NOT Hilt, just dagger) does not compile: cannot be provided without an @Inject constructor or an @Provides-annotated method
alveru opened this issue · 6 comments
I am using Android Studio - Dagger 2.35.1 (Not Hilt, just dagger), the ViewModel injection works fine using @Inject constructor() pattern, all is fun and games, but i am passing the id through a function to viewmodel which is something i do not like, so, now I am trying to implement an @assisted param in ViewModel so the ViewModel receives the param during the construction, this param comes in the activity's intent.
After adding @AssistedInject constructor() pattern to ViewModel, now dagger complains:
[Dagger/MissingBinding DetailsViewModel cannot be provided without an @Inject constructor or an @Provides-annotated method
I have searched in all the questions and examples but nobody explains the full solution or why dagger sends that error, they just post sections of code, at this point i am out of ideas what to modify to make it work
class DetailsViewModel @AssistedInject constructor(
application: Application,
val repository: DetailsRepository,
@Assisted val id: String,
) : BaseViewModel(application) {
@AssistedFactory
interface Factory { fun create(id: String) : DetailsViewModel }
companion object {
@Suppress("UNCHECKED_CAST")
fun factory(
factory: Factory,
id: String
) : ViewModelProvider.Factory {
return object : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T =
factory.create(id) as T
}
}
}
class DetailsActivity : AppCompatActivity() {
@Inject
lateinit var viewModelFactory: DetailsViewModel.Factory
private lateinit var viewModel: DetailsViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
(application as MyApplication).appComponent.inject(this)
val id = intent.getStringExtra("ID").orEmpty()
viewModel = ViewModelProvider(this, DetailsViewModel.factory(
viewModelFactory, id
))[DetailsViewModel::class.java]
}
- ViewModelModule.java:
@Module
public abstract class ViewModelModule {
@Binds
@IntoMap
@ViewModelKey(DetailsViewModel.class)
abstract ViewModel bindDetailsViewModel(DetailsViewModel viewModel);
}
- AppComponent.java:
@Singleton
@Component(modules = {AppModule.class, .class, ViewModelModule.class})
public interface AppComponent {
void inject(DetailsActivity activity);
}
Hi, @alveru , the missing binding error says that Dagger doesn't know how to provide DetailsViewModel
. This is because now that DetailsViewModel
is assisted injected, it is not included in the graph anymore. You can try removing your bindDetailsViewModel()
or ViewModelModule
.
Hello ,
thanks for your prompt response, what you mentioned solved that problem, though now the Factory is the one sending the error, since it cannot be injected :(
error: [Dagger/MissingBinding] DetailsViewModel.Factory cannot be provided without an @Provides-annotated method.
void inject(DetailsActivity activity);
i tried putting @AssistedInject too in the variable but didn't work:
class DetailsActivity : AppCompatActivity() {
@AssistedInject
lateinit var viewModelFactory: DetailsViewModel.Factory
-
I also tried adding @singleton to the factory but that failed too
companion object {
@Suppress("UNCHECKED_CAST")
@singleton
fun factory(
factory: Factory,
id: String
) : ViewModelProvider.Factory {
return object : ViewModelProvider.Factory {
override fun create(modelClass: Class): T =
factory.create(id) as T
}
}
}
Do you know where should i place the provider so Dagger can inject it?
Thanks in advance
Hi, @alveru , you shouldn't need a provider for DetailsViewModel.Factory
. Could you share a minimal project to reproduce this?
thanks for your reponse, yes, i am attaching a dummy project with the similar configuration to that of my project, with java & kotlin files, it shows the same @provides error when trying to inject the viewmodel assisted factory, the project is in a zip file:
Hi, @alveru , I think it's because you're mixing Dagger 2.35.1 and 2.17 in you build.gradle.kts
:
implementation("com.google.dagger:dagger-android:2.35.1")
//implementation("com.google.dagger:dagger-android-support:2.17")
annotationProcessor("com.google.dagger:dagger-android-processor:2.17")
annotationProcessor("com.google.dagger:dagger-compiler:2.17")
//debugImplementation("androidx.compose.ui:ui-test-manifest:1.8.2")
kapt("com.google.dagger:dagger-android-processor:2.17")
kapt("com.google.dagger:dagger-compiler:2.17")
You'll have to allign all Dagger artifacts to the same version and it has to be higher than 2.31, where assisted injection was introduced.
hi @kuanyingchou ,
thanks for your quick response, i tried it in the dummy project and then in the real project, i moved versions and now is working,
implementation 'com.google.dagger:dagger-android:2.51'
//implementation 'com.google.dagger:dagger-android-support:2.17'
//annotationProcessor 'com.google.dagger:dagger-android-processor:2.17'
annotationProcessor 'com.google.dagger:dagger-compiler:2.48'
//kapt 'com.google.dagger:dagger-android-processor:2.17'
kapt 'com.google.dagger:dagger-compiler:2.48'
i am closing the ticket, thanks for your prompt support!