Using Hilt2.48.1 version, it is not compatible with BaseViewModel
The BaseActivity I use encapsulates BaseViewModel, and an error is reported during compilation. The code and error message are as follows error message: public abstract static class SingletonC implements AppApplication_GeneratedInjector, ^ Injection of an @HiltViewModel class is prohibited since it does not create a ViewModel instance correctly. Access the ViewModel via the Android APIs (e.g. ViewModelProvider) instead. Injected ViewModel: com.maxvision.myapplication.YourViewModel
com.maxvision.myapplication.YourViewModel is injected at
com.maxvision.myapplication.base.BaseActivity.viewModel
com.maxvision.myapplication.MainActivity is injected at
com.maxvision.myapplication.MainActivity_GeneratedInjector.injectMainActivity(com.maxvision.myapplication.MainActivity) [com.maxvision.myapplication.AppApplication_HiltComponents.SingletonC → com.maxvision.myapplication.AppApplication_HiltComponents.ActivityRetainedC → com.maxvision.myapplication.AppApplication_HiltComponents.ActivityC]
code show as below: `abstract class BaseActivity <VM : BaseViewModel, DB : ViewDataBinding> : AppCompatActivity() {
@Inject
lateinit var viewModel: VM
lateinit var binding: DB
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, getLayoutResId())
binding.lifecycleOwner = this
}
//获取布局资源id
abstract fun getLayoutResId(): Int
}`
` @HiltViewModel class YourViewModel @Inject constructor( private val apiService: ApiService ) : BaseViewModel() {
}
`
` @AndroidEntryPoint class MainActivity : BaseActivity<YourViewModel, ActivityMainBinding>(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun getLayoutResId(): Int = R.layout.activity_main
}
@HiltAndroidApp
class AppApplication : Application() {
override fun onCreate() {
super.onCreate()
}
companion object {
private val sInstance: Application? = null
}
} `
The issue you're facing stems from how Hilt handles @HiltViewModel-annotated classes and how you're trying to inject your ViewModel directly into BaseActivity. This is not allowed in Hilt 2.48.1 (or any recent Hilt version), because:
You cannot inject a @HiltViewModel ViewModel using @Inject lateinit var viewModel: VM directly.
Instead, Hilt requires you to use the ViewModelProvider APIs to create and retrieve @HiltViewModel classes properly, so it can attach the correct lifecycle scope.
Solution You need to remove field injection for your ViewModel in BaseActivity and use ViewModelProvider to get the ViewModel like this:
Step-by-Step Fix
- Remove @Inject from the viewModel field
abstract class BaseActivity<VM : BaseViewModel, DB : ViewDataBinding> : AppCompatActivity() {
protected lateinit var viewModel: VM
protected lateinit var binding: DB
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, getLayoutResId())
binding.lifecycleOwner = this
}
abstract fun getLayoutResId(): Int
abstract fun createViewModel(): VM
} 2. Initialize ViewModel in your subclass using ViewModelProvider
@AndroidEntryPoint class MainActivity : BaseActivity<YourViewModel, ActivityMainBinding>() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = createViewModel()
// Now you can use viewModel here
}
override fun getLayoutResId(): Int = R.layout.activity_main
override fun createViewModel(): YourViewModel {
return ViewModelProvider(this)[YourViewModel::class.java]
}
} Alternatively, you can use Kotlin property delegate:
private val viewModel: YourViewModel by viewModels() But this won’t work generically in BaseActivity, so keep it in subclasses.
Why It Fails with @Inject Hilt uses a special mechanism (@HiltViewModel) that internally uses SavedStateHandle and lifecycle-aware scoping. Trying to inject the ViewModel directly bypasses this mechanism, and causes:
Injection of an @HiltViewModel class is prohibited...