Hilt + view model dont build - android

I have ViewModel
#HiltViewModel
class WControlViewModel #Inject constructor(
private val getProfile: GetProfile,
private val getHistory: GetHistory,
) : ViewModel() {...}
Activity
#AndroidEntryPoint
class MainActivity : ComponentActivity() {
private val vModel: WControlViewModel by viewModels()
Application
#HiltAndroidApp
class WControlApp :Application()
But project not build, error :
return DefaultViewModelFactories.getActivityFactory(this);
^
required: ComponentActivity,Factory
found: Hilt_MainActivity
reason: actual and formal argument lists differ in length

I had the same issue, which I resolved by ensuring the hilt plugin version was upgraded. In my case I went from 2.33-beta to 2.35.1
So in the dependency in your project’s root build.gradle file
classpath "com.google.dagger:hilt-android-gradle-plugin:2.35.1"
You can find the latest version numbers here: https://mvnrepository.com/artifact/com.google.dagger/hilt-android-gradle-plugin

I had faced same issue so, I changed my project level dependency and app level dependency.
Try this
in App Level Gradle:
implementation "com.google.dagger:hilt-android:2.35.1"
kapt "com.google.dagger:hilt-android-compiler:2.35.1"
in Project Level Gradle:
classpath "com.google.dagger:hilt-android-gradle-plugin:2.35.1"
Happy Coding!!

Related

Unable to build when Added new Activity in project having Hilt - Android

In my project, using dagger-Hilt
just by adding a new activity, it shows an error
:app:kaptDebugKotlin
[Hilt]
java.lang.reflect.InvocationTargetException (no error message)
but before adding a new activity, the whole project works fine
Activity :->
#AndroidEntryPoint
class SplashScreen : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash_screen)
}
}
my build.gradle
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
classpath("com.google.dagger:hilt-android-gradle-plugin:2.38.1")
I have reproduced your issue. The real problem is with versions,your kotlin version is not compatible with hilt plugin version and hilt library version. Here are the few changes you need to do.
In project build.gradle, update hilt plugin version to 2.42
classpath("com.google.dagger:hilt-android-gradle-plugin:2.42")
In app build.gradle, update to latest versions like below.
implementation("com.google.dagger:hilt-android:2.42")
kapt("com.google.dagger:hilt-android-compiler:2.42")
kapt "androidx.hilt:hilt-compiler:1.0.0"
Hilt lifecycle module not required in latest hilt version.
You should remove the below line in build.gradle and remove all androidx.hilt.lifecycle.ViewModelInject imports in your project.Other wise it will throw error
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02"

How to solve missing InjectedFieldSignature Error implementing Dagger 2 in android?

I have implemented dependency injection in android before using dagger 2 but, recently, I have tried to use it in a new project but I get the following error:
error: cannot find symbol
import dagger.internal.InjectedFieldSignature;
^
symbol: class InjectedFieldSignature
location: package dagger.internal/location/to/App_MembersInjector.java:30: error: cannot find symbol
Here is my Application component:
#Singleton
#Component(
modules = [
(AndroidInjectionModule::class),
(VmModule::class),
(InjectorModule::class),
]
)
interface ApplicationComponent: AndroidInjector<Application> {
#Component.Builder
interface Builder{
#BindsInstance
fun application(application: App): Builder
fun build() : ApplicationComponent
}
fun inject(home: Home)
}
Then in my App class:
class App: Application(), HasAndroidInjector {
#Inject
lateinit var anAndroidInjector: DispatchingAndroidInjector<Any>
override fun onCreate() {
super.onCreate()
DaggerApplicationComponent.builder().application(this).build().inject(this)
}
override fun androidInjector(): AndroidInjector<Any> {
return anAndroidInjector
}
}
Then the injector module:
#Module
abstract class InjectorModule {
#ContributesAndroidInjector
abstract fun bindHomeActivity(): Home
}
The following is a small excerpt of my app Gradle to show the dagger version:
implementation 'com.google.dagger:dagger-android:2.24'
implementation 'com.google.dagger:dagger-android-support:2.24'
kapt 'com.google.dagger:dagger-android-processor:2.24'
kapt 'com.google.dagger:dagger-compiler:2.28'
If you have any clue, kindly let me know where the problem might be.
Your Dagger artifact versions don't match. Specifically, you are using dagger-compiler:2.28 to generate code, but including an dependency on Dagger 2.24 instead.
In the specific case of dagger.internal.InjectedFieldSignature, that class appears to have been introduced in Dagger version 2.25.3. Any later version of the Dagger compiler will expect that InjectedFieldSignature exists and can be used in generated code. However, since you're only including Dagger 2.24 in your project, the generated code ends up referring to a class that doesn't exist.
To fix this, make sure all of your Dagger dependencies use the same version.

Cannot create instance of viewmodel after using Hilt in Android

Here is my AllFilesListViewModel class.
class AllFilesListViewModel #ViewModelInject constructor(
private val pdfItemRepository: PdfItemRepository):ViewModel() {
}
Here is PdfItemRepository class.
#Singleton
class PdfItemRepository #Inject constructor(private val pdfItemDao: PdfItemDao){
}
For pdfItemDao. I created a module named DatabaseModule. Below is the code -
#Module
#InstallIn(ApplicationComponent::class)
object DatabaseModule {
#Provides
fun provideDatabase(#ApplicationContext context: Context):AppDatabase{
return AppDatabase.getDataBase(context)
}
#Provides
fun providePdfItemDao(database:AppDatabase):PdfItemDao{
return database.pdfItemDao()
}
}
Here is the fragment class AllFilesFragment.kt where I am using viewModel.
#AndroidEntryPoint
class AllFilesFragment:Fragment(){
private lateinit var binding:AllFilesFragmentBinding
private val viewModel by viewModels<AllFilesListViewModel>()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = AllFilesFragmentBinding.inflate(inflater,container,false)
context?: return binding.root
initThings()
subscribeUi()
return binding.root
}
}
Here is logcat file.
06-19 19:22:20.203 23753-23753/com.emptysheet.pdfreader_autoscroll E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.emptysheet.pdfreader_autoscroll, PID: 23753
java.lang.RuntimeException: Cannot create an instance of class com.emptysheet.pdfreader_autoscroll.homeScreen.viewModel.AllFilesListViewModel
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:221)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:278)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:106)
at androidx.hilt.lifecycle.HiltViewModelFactory.create(HiltViewModelFactory.java:69)
at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:69)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:185)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:54)
at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:41)
at com.emptysheet.pdfreader_autoscroll.homeScreen.AllFilesFragment.getViewModel(AllFilesFragment.kt)
at com.emptysheet.pdfreader_autoscroll.homeScreen.AllFilesFragment.subscribeUi(AllFilesFragment.kt:72)
at com.emptysheet.pdfreader_autoscroll.homeScreen.AllFilesFragment.onCreateView(AllFilesFragment.kt:64)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:442)
at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2169)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1992)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1947)
at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1818)
at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:297)
at androidx.viewpager2.adapter.FragmentStateAdapter.placeFragmentInViewHolder(FragmentStateAdapter.java:341)
at androidx.viewpager2.adapter.FragmentStateAdapter.onViewAttachedToWindow(FragmentStateAdapter.java:276)
at androidx.viewpager2.adapter.FragmentStateAdapter.onViewAttachedToWindow(FragmentStateAdapter.java:67)
at androidx.recyclerview.widget.RecyclerView.dispatchChildAttached(RecyclerView.java:7556)
at androidx.recyclerview.widget.RecyclerView$5.addView(RecyclerView.java:860)
at androidx.recyclerview.widget.ChildHelper.addView(ChildHelper.java:107)
at androidx.recyclerview.widget.RecyclerView$LayoutManager.addViewInt(RecyclerView.java:8601)
at androidx.recyclerview.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:8559)
at androidx.recyclerview.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:8547)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1641)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
at android.view.View.layout(View.java:15689)
at android.view.ViewGroup.layout(ViewGroup.java:5048)
at androidx.viewpager2.widget.ViewPager2.onLayout(ViewPager2.java:527)
at android.view.View.layout(View.java:15689)
at android.view.ViewGroup.layout(ViewGroup.java:5048)
at com.google.android.material.appbar.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:148)
at com.google.android.material.appbar.V
This happens to me when using Hilt , and that was because I forgot to add the #AndroidEntryPoint annotation on top of the fragment class.
Both the fragment and the host activity should be annotated with this annotation.
This got solved after I used kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01' in app's build.gradle. I had already added kapt "com.google.dagger:hilt-android-compiler:2.28-alpha". I still didn't understand the difference between two BTW. If anyone knows. Please explain it to me.
This is caused by a version mismatch between AndroidX Lifecycle, AndroidX Core, AndroidX Activity and AndroidX Fragment.
Hilt only works if getDefaultViewModelProviderFactory can be overridden.
This is only true if that method actually exists, which it doesn't if your dependencies are out of date. Namely, your androidx.fragment is lower than 1.2.0, and your androidx.activity is lower than 1.1.0.
Use this and it'll work:
implementation "androidx.appcompat:appcompat:1.4.1"
implementation "androidx.core:core-ktx:1.7.0"
implementation "androidx.activity:activity-ktx:1.4.0"
implementation "androidx.fragment:fragment-ktx:1.4.1"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.4.1"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.4.1"
But currently, this is what makes it work for me:
buildscript {
ext {
dagger_version = '2.41'
}
dependencies {
classpath "com.google.dagger:hilt-android-gradle-plugin:$dagger_version"
}
and
apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'kotlin-kapt'
implementation "com.google.dagger:dagger:$dagger_version"
kapt "com.google.dagger:dagger-compiler:$dagger_version"
implementation "com.google.dagger:hilt-android:$dagger_version"
kapt "com.google.dagger:hilt-android-compiler:$dagger_version"
kaptTest "com.google.dagger:hilt-android-compiler:$dagger_version"
kaptAndroidTest "com.google.dagger:hilt-android-compiler:$dagger_version"
kapt 'androidx.hilt:hilt-compiler:1.0.0'
#ViewModelInject is deprecated in the newer hilt version
Reference
Use HiltViewModel
#HiltViewModel
class AllFilesListViewModel #Inject constructor(
val pdfItemRepository: PdfItemRepository)
) : ViewModel() {
}
When I use Jetpack Compose, Hilt and Compose Navigation, my approach is to get all the dependencies in the docs, and make sure that all of their versions are up-to-date. The key is when you create ViewModel, you shouldn't use = viewModel() beacause you have use Compose Navigation, = hiltViewModel() should be used instead.
Jetpack Compose + ViewModel in NavGraph
This answer is for people who using Jetpack Compose and navigation (NavGraph)
According to Hilt and Navigation in documentation we have to use hiltViewModel instead of viewModel
Example:
dependencies {
implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
}
// import androidx.hilt.navigation.compose.hiltViewModel
#Composable
fun MyApp() {
NavHost(navController, startDestination = startRoute) {
composable("example") { backStackEntry ->
// Creates a ViewModel from the current BackStackEntry
// Available in the androidx.hilt:hilt-navigation-compose artifact
val viewModel = hiltViewModel<MyViewModel>()
MyScreen(viewModel)
}
/* ... */
}
}
More and fresh information in the source
I faced this issue before and I have fixed it by passing SavedStateHandle to the main constructor of the view model.
class AuthViewModel #ViewModelInject constructor(#Assisted private val savedState: SavedStateHandle) : ViewModel()
For those who checked all the above solutions and still not working then the final check is to delete the Build folder and rebuild the project this will force the compiler to re-create the dagger dependency graph under the hood.
In my case, I have annotated my activity with #AndroidEntryPoint still facing the same issue. I have deleted my build folder and rebuild the project and it is working as expected.
In alpha03, Use the new #HiltViewModel and the normal #Inject now as shown below.
#HiltViewModel
class MyViewModel #Inject constructor(
private val repository: Repository,
private val savedStateHandle: SavedStateHandle
) : ViewModel(), LifecycleObserver {
// Some code
}
I have also faced this problem today, I tried all the possible fixes suggested but it was impossible to remove the error. I just post my solution here in case someone has the same problem in the future.
In my case I have a multi-module project, with 'UI module', 'ViewModel module' and 'Use-cases module'. The error on my side was that I was not importing all the modules in the application's gradle module, I was only importing UI module. I found this note in the Android developers website regarding hilt implementation:
Note: Because Hilt's code generation needs access to all of the Gradle modules that use Hilt, the Gradle module that compiles your Application class also needs to have all of your Hilt modules and constructor-injected classes in its transitive dependencies.
When I imported all the modules that were needed to generate the DI graph, this crash disappeared.
for me resolvec when moved = viewModel() from Compose function to Activity

Runtime JAR files in the classpath should have the same version

I have a project which I use Dagger2 & kotlin, I imported "org.jetbrains.kotlin:kotlin-stdlib:1.3.50” in my build.gradle and I was getting this Error:
w: Runtime JAR files in the classpath should have the same version.
These files were found in the classpath:
w:
/Users/macbook/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jre7/1.1.51/8b5933578dc55f32cfc1a25f1db6371e4161fb8f/kotlin-stdlib-jre7-1.1.51.jar:
kotlin-stdlib-jre7 is deprecated. Please use kotlin-stdlib-jdk7
instead
So therefore I changed from "kotlin-stdlib" to "kotlin-stdlib-jdk7" using:
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50” and I am still getting this error.
I then made some research and found this URL: warning: Kotlin runtime JAR files in the classpath should have the same version
I found the usage of kotlin-reflect: "implementation "org.jetbrains.kotlin:kotlin-reflect:1.3.50"
I added it to my build.gradle BUT I still have the same errors
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7: 1.3.50"
implementation "org.jetbrains.kotlin:kotlin-reflect: 1.3.50"
This is my BaseApplication class below, which I am calling the Dagger components :
class BaseApplication : Application() {
companion object {
#JvmStatic lateinit var netComponent: NetComponent
#JvmStatic lateinit var exampleComponent: ExampleComponent
}
override fun onCreate() {
super.onCreate()
netComponent = DaggerNetComponent.builder()
.appModule(AppModule(this))
.netModule(NetModule())
.build()
exampleComponent = DaggerExampleComponent.builder()
.netComponent(netComponent)
.retrofitModule(RetrofitModule())
.exampleModule(ExampleModule(this))
.build()
}
}

Mockito is not recognized by Android (Kotlin)

Here is my class test:
private const val FAKE_STRING = "APP NAME"
#RunWith(MockitoJUnitRunner::class)
class UnitTestSample {
#Mock
private lateinit var mockContext: Context
#Test
fun readStringFromContext_LocalizedString() {
// Given a mocked Context injected into the object under test...
`when`(mockContext.getString(R.string.app_name))
.thenReturn(FAKE_STRING)
val myObjectUnderTest = ClassUnderTest(mockContext)
// ...when the string is returned from the object under test...
val result: String = myObjectUnderTest.getHelloWorldString()
// ...then the result should be the expected one.
assertThat(result, `is`(FAKE_STRING))
}
}
Here is a piece of my gradle.build.kt (Kotlin DSL):
plugins {
id("com.android.application")
kotlin("android")
kotlin("kapt")
kotlin("android.extensions")
id("com.onesignal.androidsdk.onesignal-gradle-plugin")
jacoco
maven
}
dependencies {
...
//Test base
testImplementation("junit:junit:4.12")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.0.3")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.0.3")
androidTestImplementation("androidx.test:runner:1.2.0")
androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0")
//Unit Tests
testImplementation("org.mockito:mockito-core:3.0.0")
testImplementation("org.mockito:mockito-inline:3.0.0") //support for kotlin final classes
//Android UI Test
androidTestImplementation("org.robolectric:robolectric:3.7.1")
}
As you can see, Android Studio doesn't reognize Mockito. I've already imported org.mockito.junit.MockitoJUnitRunner
I'm running this sample unit test under
src/test/java/.../UnitTestSample.kt
Do you have any idea on how to make it work?
Edit (Solution):
I finally made it work with some help of the comments section. The problem was caused by "maven" plugin import on plugins section, and I didn't see that because the base project I downloaded to convert my Gradle to DSL Kotlin had those plugins working. Somehow this was causing Mockito not to be available at compile time, as #MartinZeitler stated. According to #second, "Maven's runtime does not translate to gradle's runtimeOnly but instead compile".
The error message is pretty clear: an annotation argument must be a compile time argument.
Replace testImplementation with:
debugImplementation "org.mockito:mockito-android:3.2.4"
debugImplementation "org.mockito:mockito-inline:3.2.4"
Edit: Cleaned up the answer
For JUnit5 and mockito use the following dependencies (or newer) and scopes:
testImplementation("org.junit.jupiter:junit-jupiter-api:5.4.2")
compile("org.junit.jupiter:junit-jupiter-engine:5.4.2")
testImplementation("org.mockito:mockito-core:3.0.0")
testImplementation("org.mockito:mockito-junit-jupiter:3.0.0")
testImplementation("org.mockito:mockito-inline:3.0.0")
In your test use the Extension instead of the Runner (which is for JUnit 4).
#ExtendWith(MockitoExtension::class)
When running with the JUnit 5 dependencies of 5.0.3, I got the following error, so consider upgrading to a newer version (as shown in the dependencies above).
java.lang.NoSuchMethodError:
org.junit.platform.commons.support.AnnotationSupport.findAnnotation(Ljava/util/Optional;Ljava/lang/Class;)Ljava/util/Optional;
...
Suppressed: java.lang.NullPointerException
at org.mockito.junit.jupiter.MockitoExtension.afterEach(MockitoExtension.java:214)
For the maven to gradle conversion I used this site
https://sagioto.github.io/maven2gradle/

Categories

Resources