I have spent the hole week trying to add hilt dependency injection to my sample note application, android studio have been throwing on me error after an error.It got me mad, any way, in AppModule i have been trying to inject my room database to app repository and then my app repo to my use cases class and at the end injecting use cases class to my sharedViewModel
so this is my AppModule object:
#Module
#InstallIn(SingletonComponent::class)
object AppModule {
#Provides
#Singleton
fun provideNoteDatabase(app: Application): NoteDatabase {
return Room.databaseBuilder(
app,
NoteDatabase::class.java,
NoteDatabase.DATABASE_NAME
).build()
}
#Provides
#Singleton
fun provideNoteRepository(db: NoteDatabase): NotesRepo {
return RepoImplementation(db.noteDao())
}
#Provides
#Singleton
fun provideNoteUseCase(repo: NotesRepo): NoteUseCase {
return NoteUseCase(
getNotesUseCase = GetNotesUseCase(repo),
deleteNoteUseCase = DeleteNoteUseCase(repo),
updateNoteUseCase = UpdateNoteUseCase(repo),
insertNoteUseCase = InsertNoteUseCase(repo)
)
}
}
and this my Application class:
#HiltAndroidApp
class Application : Application()
my edit fragment:
#AndroidEntryPoint
class EditFragment : Fragment() {
private var _binding: FragmentEditBinding? = null
private val binding get() = _binding!!
private val viewModel: SharedViewModel by activityViewModels()
//...
}
my other fragment:
#AndroidEntryPoint
class MainFragment : Fragment() {
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
private val viewModel: SharedViewModel by activityViewModels()
//...
}
by the way also my MainActivity is annotated with #AndroidEntryPoint
my famous viewModel :
#HiltViewModel
class SharedViewModel #Inject constructor(private val noteUseCase: NoteUseCase) :
ViewModel() {...}
this is project level build.gradle:
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
def nav_version = "2.5.2"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.44'
}
}
plugins {
id 'com.android.application' version '7.3.0' apply false
id 'com.android.library' version '7.3.0' apply false
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
}
and module level build.gradle:
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-android'
id 'kotlin-kapt'
id "androidx.navigation.safeargs"
id 'com.google.dagger.hilt.android'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.stayin"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
dataBinding true
viewBinding true
}
namespace 'com.example.stayin'
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
def lifecycle_version = "2.4.1"
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
// coroutines for getting off the UI thread
def coroutines = "1.6.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
//shared preferences dependency
implementation 'androidx.preference:preference-ktx:1.2.0'
// Room dependency
def room_version = "2.4.3"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
// Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"
//navigation component dependency
implementation "androidx.navigation:navigation-fragment-ktx:2.5.2"
implementation "androidx.navigation:navigation-ui-ktx:2.5.2"
//Dagger - Hilt
implementation 'com.google.dagger:hilt-android:2.44'
kapt 'com.google.dagger:hilt-compiler:2.44'
// For instrumentation tests
androidTestImplementation 'com.google.dagger:hilt-android-testing:2.44'
kaptAndroidTest 'com.google.dagger:hilt-compiler:2.44'
// For local unit tests
testImplementation 'com.google.dagger:hilt-android-testing:2.44'
kaptTest 'com.google.dagger:hilt-compiler:2.44'
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
}
if can any one help me to find what is wrong and explained why, i will be so thankful towards him. i rally need to pass this so i can level up in my career.
Remove below deprecated dependency:
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
(It was deprecated since dagger-2.34 version)
proof:
https://github.com/google/dagger/releases/tag/dagger-2.34
Also Try to upgrade your lifecycle version as below:
def lifecycle_version = "2.5.1"
add below lines after dependency section in build.gradle(app):
kapt { correctErrorTypes true }
follow official documentation:
https://developer.android.com/training/dependency-injection/hilt-android
https://dagger.dev/hilt/view-model.html
Related
I was writing unit tests for my room db operations, everything was working great but, I decided to write and inject the DataBaseBuilder within TestAppModule using Hilt, but seems like I am getting the following error when i run the tests. I also created a custom HiltRunnerClass and used it in gradle as testInstrumentationRunner "com.rimapps.wisetest.HiltTestRunner"
here is full error
error: [Hilt]
Null element: java.lang.NullPointerException: Null element
at dagger.hilt.processor.internal.root.AutoValue_Root.<init>(AutoValue_Root.java:19)
at dagger.hilt.processor.internal.root.Root.createDefaultRoot(Root.java:46)
at
[Hilt] Processing did not complete. See error above for details.
1 error
here is the code
HiltTestRunner.kt
class HiltTestRunner:AndroidJUnitRunner() {
override fun newApplication(
cl: ClassLoader?,
className: String?,
context: Context?
): Application {
return super.newApplication(cl, HiltTestApplication::class.java.name, context)
}
}
NewsArticleDaoTest.kt
#RunWith(AndroidJUnit4::class)
#SmallTest
#HiltAndroidTest
class NewsArticleDaoTest{
#get:Rule
var hiltRule = HiltAndroidRule(this)
#get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
#Inject
#Named("test_db")
lateinit var database: NewsArticleDatabase
//private lateinit var database: NewsArticleDatabase
private lateinit var dao: NewsArticleDao
#Before
fun setup(){
hiltRule.inject()
dao = database.newsArticleDao()
// database = Room.inMemoryDatabaseBuilder(
// ApplicationProvider.getApplicationContext(),
// NewsArticleDatabase::class.java
// ).allowMainThreadQueries().build()
dao = database.newsArticleDao()
}
#After
fun teardown(){
database.close()
}
#Test
fun insertNewsArticle() = runTest {
val testArticle = NewsArticle("Time traveller shares footage from three weeks in the future showing who wins the World Cup","https://www.ladbible.com/sport/time-traveller-who-wins-world-cup-2022-20221128","https://images.ladbible.com/resize?type=webp&quality=70&width=671&fit=contain&gravity=null&dpr=2&url=https://eu-images.contentstack.com/v3/assets/bltcd74acc1d0a99f3a/bltb6064933a4b82b9c/6384c84adb8e364b186bfb6c/Most_prolific_speed_camera_in_the_UK_has_caught_almost_50_000_drivers_this_year_(42).png")
val testItem = listOf(testArticle)
dao.insertArticles(testItem)
val testFeed = NewsFeed(testArticle.url)
val feedTestItem = listOf(testFeed)
dao.insertNewsFeed(feedTestItem)
val allNewsArticles = dao.getAllNewsArticles().first()
assertThat(allNewsArticles).contains(testArticle)
}
#Test
fun deleteAllArticles()= runTest {
val testArticle = NewsArticle("Time traveller claims discovery of mysterious sea creature will change world","https://www.dailystar.co.uk/news/weird-news/time-traveller-claims-discovery-mysterious-28766022","https://i2-prod.dailystar.co.uk/incoming/article28766081.ece/ALTERNATES/s615b/1_A-SELF-proclaimed-time-traveller-from-2198-claims-experts-will-soon-make-a-chilling-ocean-discovery.jpg")
val testItem = listOf(testArticle)
dao.insertArticles(testItem)
val testFeed = NewsFeed(testArticle.url)
val feedTestItem = listOf(testFeed)
dao.insertNewsFeed(feedTestItem)
dao.deleteAllNewsFeed()
val allArticles = dao.getAllNewsArticles().first()
assertThat(allArticles).doesNotContain(testArticle)
}
}
TestAppModule.kt
#Module
#InstallIn(SingletonComponent::class)
object TestAppModule {
#Provides
#Named("test_db")
fun provideInMemoryDb(#ApplicationContext context: Context) =
Room.inMemoryDatabaseBuilder(context,NewsArticleDatabase::class.java )
.allowMainThreadQueries()
.build()
}
gladle(app)
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
id 'kotlin-parcelize'
id 'androidx.navigation.safeargs'
}
android {
compileSdkVersion 33
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.rimapps.wisetest"
minSdkVersion 21
targetSdkVersion 33
versionCode 1
versionName "1.0"
//testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "com.rimapps.wisetest.HiltTestRunner"
buildConfigField("String", "NEWS_API_ACCESS_KEY", news_api_access_key)
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
buildFeatures {
viewBinding true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
freeCompilerArgs += "-Xopt-in=androidx.paging.ExperimentalPagingApi"
freeCompilerArgs += "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.5.1'
//noinspection GradleDependency
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
testImplementation 'org.junit.jupiter:junit-jupiter'
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
// Glide
implementation "com.github.bumptech.glide:glide:4.14.2"
// Dagger Hilt
implementation "com.google.dagger:hilt-android:2.44.2"
kapt "com.google.dagger:hilt-android-compiler:2.44.2"
// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
// Retrofit + GSON
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
// Room
implementation "androidx.room:room-runtime:2.5.0-rc01"
kapt "androidx.room:room-compiler:2.5.0-rc01"
implementation "androidx.room:room-ktx:2.5.0-rc01"
// SwipeRefreshLayout
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
// Paging 3
implementation "androidx.paging:paging-runtime-ktx:3.2.0-alpha03"
// Fragment
implementation 'androidx.fragment:fragment-ktx:1.6.0-alpha04'
// Local Unit Tests
implementation "androidx.test:core:1.5.0"
testImplementation "junit:junit:4.13.2"
testImplementation "org.hamcrest:hamcrest-all:1.3"
testImplementation "androidx.arch.core:core-testing:2.1.0"
testImplementation "org.robolectric:robolectric:4.3.1"
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4"
testImplementation "com.google.truth:truth:1.0.1"
testImplementation "org.mockito:mockito-core:3.4.6"
// Instrumented Unit Tests
androidTestImplementation "junit:junit:4.13.2"
androidTestImplementation "org.mockito:mockito-android:2.25.0"
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4"
androidTestImplementation "androidx.arch.core:core-testing:2.1.0"
androidTestImplementation "com.google.truth:truth:1.0.1"
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
androidTestImplementation "org.mockito:mockito-core:3.4.6"
androidTestImplementation 'com.google.dagger:hilt-android-testing:2.28-alpha'
kaptAndroidTest 'com.google.dagger:hilt-android-compiler:2.44.2'
debugImplementation "androidx.fragment:fragment-testing:1.5.5"
}
kapt {
correctErrorTypes true
}
gradle(project)
buildscript {
ext.kotlin_version = "1.7.20"
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.6.0-alpha04"
classpath "com.google.dagger:hilt-android-gradle-plugin:2.44.2"
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
I am trying to create MVVM app using Openweathermap API and hilt. I tried to inject my repository into my viewmodel primary constractor and creating a ViewModelFactory class, in order to pass the parameters from viewmodel class to my main activity class it did not work with 'by viewmodels()' itself. Sadly it did not work and I am getting the following message "has no zero argument constructor". It worth to mention that I also tried to inject the repository into my secondary constractor.
This is my MainActivity
#AndroidEntryPoint
class MainActivity
#Inject constructor(var repository:WeatherRepositoryInterface) : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var previewAdapter: PreviewAdapter
lateinit var viewModel:WeatherViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
initViewItems()
}
fun initViewItems() {
viewModel= ViewModelProvider(this#MainActivity,FactoryViewModel(application,repository))[WeatherViewModel::class.java]
binding.recyclerview.apply {
layoutManager = LinearLayoutManager(this#MainActivity)
previewAdapter = PreviewAdapter(viewModel.loadCities().value!!)
previewAdapter.let {
it.setOnItemClickListener(object: OnClickInterface{
override fun onClickItem(position: Int) {
var intent=Intent(this#MainActivity,DetailActivity::class.java)
intent.putExtra("name",viewModel.loadCities().value!![position].cityName)
intent.putExtra("img",viewModel.loadCities().value!![position].cityImg)
startActivity(intent)
}
})
}
adapter = previewAdapter
}
}
}
My ViewModel class
#HiltViewModel
class WeatherViewModel #Inject constructor(application: Application, var repository: WeatherRepositoryInterface)
: AndroidViewModel(application) ,LifecycleObserver{
companion object{
private val VIEWMODEL_STRING="WeatherViewModel.class"
}
private var list: MutableLiveData<List<Preview>> = MutableLiveData()
fun getCityInfo(q:String) =
liveData(Dispatchers.IO){
emit(com.example.yourweatherapp.Resources.Resource.loading(data = null))
try {
emit(com.example.yourweatherapp.Resources.Resource.success(data = repository.getWeather(q=q)))
} catch (e: Exception) {
emit(e.message?.let { com.example.yourweatherapp.Resources.Resource.error(data = null, message = it) })
e.message?.let { Log.e(VIEWMODEL_STRING, it) }
}
}
fun loadCities():MutableLiveData<List<Preview>>{
list.value= listOf(
Preview(
CityList.santorini,
CityList.santoriniImg),
Preview(CityList.bern,
CityList.bernImg),
Preview(CityList.venice,
CityList.veniceImg),
Preview("",CityList.myLocationImg)
)
return list
}
}
My ViewModelFactory class:
class FactoryViewModel(
var application:Application,
var repository: WeatherRepositoryInterface
): ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel> create(modelClass: Class<T>): T =
WeatherViewModel(application,repository) as T
}
My Gradle dependency file:
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
}
android {
compileSdk 31
defaultConfig {
applicationId "com.example.yourweatherapp"
minSdk 21
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildFeatures {
dataBinding = true
viewBinding = true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
implementation 'androidx.navigation:navigation-fragment-ktx:2.4.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.4.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation("androidx.cardview:cardview:1.0.0")
implementation 'com.github.bumptech.glide:glide:4.12.0'
implementation("androidx.cardview:cardview:1.0.0")
implementation("androidx.recyclerview:recyclerview:1.2.1")
// implementation ("androidx.lifecycle:lifecycle-livedata:2.5.0-alpha01")
//http3
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.3"))
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.0-alpha01"
implementation "androidx.activity:activity-ktx:1.1.0"
implementation("com.squareup.okhttp3:okhttp")
implementation("com.squareup.okhttp3:logging-interceptor")
//lifecycle
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.4.0"
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0")
kapt("androidx.lifecycle:lifecycle-compiler:2.5.0-alpha01")
implementation("androidx.lifecycle:lifecycle-common-java8:2.5.0-alpha01")
implementation("androidx.lifecycle:lifecycle-service:2.5.0-alpha01")
//fragment
implementation("androidx.fragment:fragment-ktx:1.4.1")
implementation("androidx.navigation:navigation-fragment-ktx:2.4.1")
implementation("androidx.navigation:navigation-ui-ktx:2.4.1")
//hilt dagger
implementation("com.google.dagger:hilt-android:2.38.1")
kapt("com.google.dagger:hilt-android-compiler:2.38.1")
//implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2"
implementation 'androidx.hilt:hilt-navigation-compose:1.0.0'
implementation 'androidx.hilt:hilt-navigation-compose:1.0.0'
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03'
kapt 'androidx.hilt:hilt-compiler:1.0.0'
}
kapt {
javacOptions {
// These options are normally set automatically via the Hilt Gradle plugin, but we
// set them manually to workaround a bug in the Kotlin 1.5.20
option("-Adagger.fastInit=ENABLED")
option("-Adagger.hilt.android.internal.disableAndroidSuperclassValidation=true")
}
}
Just remove this line from your dependencies:
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03'
I found this in migrations doc and solved the issue for my case:
Remove this line from gradle:
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03'
I'm using latest versions of all dependencies, make sure to check and apply all related and necessary migrations
After going through documentations and trying solutions of similar questions here on stackoverflow, nothing seems to fix the issue.
I tried altering all related dependencies, trying additional dependencies and tweaking the versions. Gradle builds successfully but there is a runtime error that through trial and error, the only method I found that could fix it was removing the argument from the ViewModel which is not desirable for me as the same setup used to work in my older projects.
RuntimeException
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example, PID: 17527
java.lang.RuntimeException: Cannot create an instance of class com.example.ui.MainViewModel
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:188)
build.gradle(:app)
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
id 'com.google.devtools.ksp' version '1.6.10-1.0.2'
}
kotlin {
sourceSets {
debug {
kotlin.srcDir("build/generated/ksp/debug/kotlin")
}
release {
kotlin.srcDir("build/generated/ksp/release/kotlin")
}
}
}
android {
compileSdk 31
defaultConfig {
multiDexEnabled = true
applicationId "com.example"
minSdk 23
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary true
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
freeCompilerArgs += '-Xopt-in=kotlin.RequiresOptIn'
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion compose_version
}
packagingOptions {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation "androidx.compose.ui:ui:$compose_version"
implementation 'androidx.compose.material3:material3:1.0.0-alpha04'
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'
implementation 'androidx.activity:activity-compose:1.4.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
//lifecycle
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0"
//Hilt
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-compiler:$hilt_version"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
kapt "androidx.hilt:hilt-compiler:1.0.0"
//Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'
//DataStore
implementation "androidx.datastore:datastore-preferences:1.0.0"
//Desugaring
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
//Compose Destinations
implementation "io.github.raamcosta.compose-destinations:core:1.2.1-beta"
ksp "io.github.raamcosta.compose-destinations:ksp:1.2.1-beta"
build.gradle(Project)
buildscript {
ext {
compose_version = '1.2.0-alpha02'
hilt_version = "2.40.5"
}
dependencies {
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
}
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.2.0-beta01' apply false
id 'com.android.library' version '7.2.0-beta01' apply false
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
id 'org.jetbrains.kotlin.jvm' version '1.6.10' apply false
}
task clean(type: Delete) {
delete rootProject.buildDir
}
MainViewModel.kt
#HiltViewModel
class MainViewModel #Inject constructor(
private val dataStoreRepository: DataStoreRepository
) : ViewModel() {...}
MainActivity.kt
#AndroidEntryPoint
class MainActivity : ComponentActivity() {
private val mainViewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
DestinationsNavHost(navGraph = NavGraphs.root)
}
}
}
Did you create module class? like below:
#Module
#InstallIn(SingletonComponent::class)
class RepositoryModule {
#Provides
#Singleton
fun provideDataStoreRepository(): DataStoreRepository = DataStoreRepository()
}
I am facing some issue using Room DB
java.lang.RuntimeException: cannot find implementation for
com.zeliot.roomtuto.db.NoteDB. NoteDB_Impl does not exist
below is my app grale
plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
compileSdk 31
defaultConfig {
applicationId "com.zeliot.roomtuto"
minSdk 23
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
//Room
def room_version = "2.3.0"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
// Coroutine Lifecycle Scopes
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.3.1"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
//coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0'
}
#Entity(
tableName = "note"
)
data class Note(
#PrimaryKey(autoGenerate = true)
var id:Int?=null,
val title :String,
val desciption:String,
val datetime:String,
)
#Dao
interface NoteDao {
#Insert
fun insert(note: Note)
#Delete
fun delete(note: Note)
#Query("select * from note")
fun getNotes(): LiveData<List<Note>>
#Update
fun update(note: Note)
}
#Database(
entities = [Note::class],
version = 1
)
abstract class NoteDB :RoomDatabase() {
abstract fun getNoteDao():NoteDao
companion object{
#Volatile
private var instance : NoteDB? = null
fun createDB(context: Context) :NoteDB{
return instance ?:
Room.databaseBuilder(
context.applicationContext,
NoteDB::class.java,
"Note_db.db"
)
.build()
}
}
}
UNABLE TO GET THE ANSWER ,I HAVE TRIED MANY SOLUTIONS BUT DIDN'T WORK.
I have tried many solution which are already available in stackoverflow but those solutions didnt work.
In Apple M1 chip we need to use room version of 2.4.0-alpha04.
plugins {
id 'com.android.application'
id 'kotlin-android'
id'kotlin-kapt'
}
implementation "androidx.room:room-runtime:2.4.0-alpha04"
implementation "androidx.room:room-ktx:2.4.0-alpha04"
kapt "androidx.room:room-compiler:2.4.0-alpha04"
issue tracker link https://issuetracker.google.com/issues/174695268?pli=1#comment13
Change :-
plugins {
id 'com.android.application'
id 'kotlin-android'
}
to
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
}
and then change
annotationProcessor "androidx.room:room-compiler:$room_version"
to
kapt "androidx.room:room-compiler:$room_version"
I want to inject dependencies in android tests using dagger.
I've created a simple App with an AppComponent extending AndroidInjector.
That works for the App itself (the code is built in /build by dagger).
Then, for /test I've also created the AppComponentTest and AppTest.
It took me some time to realised that I need to create a naive test and run it to let gradle create the /build for test.
Now the code is there, but there is some error with that generated code, as you can see here:
AppComponent.kt
#Singleton
#Component(
modules = [
AndroidSupportInjectionModule::class
]
)
interface AppComponent : AndroidInjector<App> {
#Component.Factory
interface Factory {
fun create(#BindsInstance application: Application): AppComponent
}
}
App.kt
open class App : Application(), HasAndroidInjector {
#Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
override fun androidInjector(): AndroidInjector<Any> = dispatchingAndroidInjector
override fun onCreate() {
super.onCreate()
setupDagger()
}
#VisibleForTesting
open fun setupDagger() {
DaggerAppComponent
.factory()
.create(this)
.inject(this)
}
}
Then under the same structure but in /test I've created this:
AppComponentTest.kt
#Singleton
#Component(
modules = [
AndroidSupportInjectionModule::class
]
)
interface AppComponentTest : AppComponent {
#Component.Factory
interface Factory {
fun create(
#BindsInstance application: Application
): AppComponentTest
}
}
AppTest.kt
class AppTest : App() {
override fun setupDagger() {
DaggerTestAppComponent
.factory()
.create(this)
.inject(this)
}
}
And this is the build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.example.dagger"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
def dagger_version = "2.27"
implementation "com.google.dagger:dagger-android:$dagger_version"
implementation "com.google.dagger:dagger-android-support:$dagger_version"
kapt "com.google.dagger:dagger-android-processor:$dagger_version"
kapt "com.google.dagger:dagger-compiler:$dagger_version"
testImplementation 'junit:junit:4.13'
kaptTest "com.google.dagger:dagger-compiler:$dagger_version"
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
Also the naive test:
ExampleUnitTest.kt
#RunWith(JUnit4::class)
class ExampleUnitTest {
#Test
fun test() {
assert(true)
}
}
I've also tried with other approach using this:
AppComponentTest2.kt
#Singleton
#Component(modules = [])
interface AppComponentTest2 {
fun inject(test: ExampleUnitTest2)
}
ExampleUnitTest2.kt
#RunWith(JUnit4::class)
class ExampleUnitTest2 {
#Test
fun test() {
DaggerAppComponentTest2
.builder()
.build()
.inject(this)
assert(true)
}
}
And also the same error:
Btw, this is a repo with that code:
https://gitlab.com/fitu/dagger
There are two branches there first_approach and second_approach
EDIT 1:
I had other repo where I was able to do this injection and now I've tried and it doesn't work.
Comparing dependencies I have:
New project:
classpath 'com.android.tools.build:gradle:3.6.1'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.61'
implementation 'com.google.dagger:dagger-android:2.27'
implementation 'com.google.dagger:dagger-android-support:2.27'
kapt 'com.google.dagger:dagger-android-processor:2.27'
kapt 'com.google.dagger:dagger-compiler:2.27'
kaptTest 'com.google.dagger:dagger-compiler:2.27'
Old project:
classpath 'com.android.tools.build:gradle:3.2.0'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.70'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.61'
implementation'com.google.dagger:dagger-android-support:2.14.1'
kapt 'com.google.dagger:dagger-compiler:2.14.1'
kaptTest 'com.google.dagger:dagger-compiler:2.14.1'
So it seems is not a dagger or kotlin version.
Maybe it's related with Android Studio?
I'm not sure about the version of AS when I'd created that old project, but my current AS version is: 3.6.1
EDIT 2:
I've deleted almost everything in the project, the main folder with App and everything:
The only reminding was two classes: AppComponentTest.kt and ExampleUnitTest.kt
#Singleton
#Component(modules = [])
interface AppComponentTest
class ExampleUnitTest {
#Test
fun test() {
DaggerAppComponentTest
.builder()
.build()
assert(true)
}
}
The error persist, so I'm guessing the problem could be a combinations of AS version, Kotlin version and/or Dagger version.