ShahZaman Rai
ShahZaman Rai

Reputation: 157

Cannot create a instace of viewModel in kotlin Android

I am using ViewModel and injecting dependencies using dagger hilt. When I launch my app it crashes and gives this error in Logs.

Cannot create an instance of ViewModel.

I have tried solutions to other questions and all permissions are included correctly in the manifest. So specific answers will be appreciated.


MainActivity

package com.shahzaman.weather.weatherFeature.presentation

import android.Manifest
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.shahzaman.weather.weatherFeature.presentation.screeens.MainScreen
import com.shahzaman.weather.weatherFeature.presentation.ui.theme.WeatherTheme
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

    private val viewModel: WeatherViewModel by viewModels()
    private lateinit var permissionLauncher: ActivityResultLauncher<Array<String>>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        permissionLauncher = registerForActivityResult(
            ActivityResultContracts.RequestMultiplePermissions()
        ) {
            viewModel.loadWeatherInfo()
        }
        permissionLauncher.launch(
            arrayOf(
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION,
            )
        )
        setContent {
            WeatherTheme {
                Box(
                    modifier = Modifier.fillMaxSize()
                ) {
                    Column(
                        modifier = Modifier
                            .fillMaxSize()
                    ) {
                        MainScreen(cityName = "Okara", state = viewModel.state)
                    }
                    if (viewModel.state.isLoading) {
                        CircularProgressIndicator(
                            modifier = Modifier.align(Alignment.Center)
                        )
                    }
                    viewModel.state.error?.let { error ->
                        Text(
                            text = error,
                            color = Color.Red,
                            textAlign = TextAlign.Center,
                            modifier = Modifier.align(Alignment.Center)
                        )
                    }
                }
            }
        }
    }
}

MainScreen

package com.shahzaman.weather.weatherFeature.presentation.screeens

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.shahzaman.weather.R
import com.shahzaman.weather.weatherFeature.presentation.WeatherState
import com.shahzaman.weather.weatherFeature.presentation.components.DailyCard
import com.shahzaman.weather.weatherFeature.presentation.components.FilledDate
import com.shahzaman.weather.weatherFeature.presentation.components.InfoCard
import com.shahzaman.weather.weatherFeature.presentation.components.TwoLines

@Composable
fun MainScreen(
    cityName: String,
    state: WeatherState
) {
    state.weatherInfo?.currentWeatherData?.let { data ->
        Column(
            modifier = Modifier.fillMaxSize(),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Header(cityName = cityName)
            Spacer(modifier = Modifier.height(32.dp))
            FilledDate(
                state = state
            )
            Spacer(modifier = Modifier.height(8.dp))
            Text(
                text = data.weatherType.weatherDesc,
                style = MaterialTheme.typography.bodyMedium,
            )
            Text(
                text = "${data.temperatureCelsius}°",
                style = MaterialTheme.typography.titleLarge
            )

            DailySummary(
                temperature = data.temperatureCelsius
            )
            Spacer(modifier = Modifier.height(16.dp))
            InfoCard(
                windValue = "${data.windSpeed}Km/h",
                humidityValue = "${data.humidity}%",
                visibilityValue = "${data.pressure}Km"
            )
            Footer()
            Spacer(modifier = Modifier.height(8.dp))
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 16.dp),
                horizontalArrangement = Arrangement.SpaceEvenly
            ) {
                DailyCard(
                    date = "11 Aug",
                    temperature = "27°",
                    icon = painterResource(id = R.drawable.humidity_filled)
                )
                DailyCard(
                    date = "12 Aug",
                    temperature = "28°",
                    icon = painterResource(id = R.drawable.humidity_filled)
                )
                DailyCard(
                    date = "13 Aug",
                    temperature = "24°",
                    icon = painterResource(id = R.drawable.humidity_filled)
                )
                DailyCard(
                    date = "14 Aug",
                    temperature = "26°",
                    icon = painterResource(id = R.drawable.humidity_filled)
                )
            }

        }
    }
}


@Composable
fun Header(
    cityName: String
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(start = 16.dp, end = 16.dp, top = 16.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween
    ) {
        TwoLines()
        Text(
            text = cityName,
            textAlign = TextAlign.Center,
            style = MaterialTheme.typography.bodyLarge
        )
        Text(
            text = "",
            modifier = Modifier.width(36.dp)
        )
    }
}

@Composable
fun DailySummary(
    temperature: Double
) {
    Column {

        Text(
            text = "Daily Summary",
            style = MaterialTheme.typography.bodySmall,
            textAlign = TextAlign.Start,
            fontWeight = FontWeight.ExtraBold,
            modifier = Modifier
                .padding(horizontal = 16.dp),
            fontSize = 22.sp
        )
        Spacer(modifier = Modifier.height(8.dp))
        Text(
            text = "Now it feels like $temperature\", actually +$temperature\".\n" +
                    "It feels hot because of the direct sun. Today,\nthe temperature is felt in the range from +31 to 27.",
            style = MaterialTheme.typography.bodySmall,
            textAlign = TextAlign.Start,
            fontWeight = FontWeight.Bold,
            modifier = Modifier
                .padding(horizontal = 16.dp),
            fontSize = 12.sp
        )
    }
}


@Composable
fun Footer(
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(start = 32.dp, end = 32.dp, top = 16.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween
    ) {
        Text(
            text = "Weekly forecast",
            style = MaterialTheme.typography.bodySmall,
            color = MaterialTheme.colorScheme.onBackground,
            textAlign = TextAlign.Start,
            fontWeight = FontWeight.ExtraBold,
            fontSize = 18.sp
        )
        Image(
            painter = painterResource(id = R.drawable.arrow_indicator),
            contentDescription = "",
            modifier = Modifier
                .size(36.dp),
        )
    }
}

WeatherViewModel

package com.shahzaman.weather.weatherFeature.presentation

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.shahzaman.weather.weatherFeature.domain.location.LocationTracker
import com.shahzaman.weather.weatherFeature.domain.repository.WeatherRepository
import com.shahzaman.weather.weatherFeature.domain.util.Resource
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class WeatherViewModel @Inject constructor(
    private val repository: WeatherRepository,
    private val locationTracker: LocationTracker
) : ViewModel() {

    var state by mutableStateOf(WeatherState())
        private set

    fun loadWeatherInfo() {
        viewModelScope.launch {
            state = state.copy(
                isLoading = true,
                error = null
            )
            locationTracker.getCurrentLocation()?.let { location ->
                when (val result =
                    repository.getWeatherData(location.latitude, location.longitude)) {
                    is Resource.Success -> {
                        state = state.copy(
                            weatherInfo = result.data,
                            isLoading = false,
                            error = null
                        )
                    }

                    is Resource.Error -> {
                        state = state.copy(
                            weatherInfo = null,
                            isLoading = false,
                            error = result.message
                        )
                    }
                }
            } ?: kotlin.run {
                state = state.copy(
                    isLoading = false,
                    error = "Couldn't retrieve location. Make sure to grant permission and enable GPS."
                )
            }
        }
    }
}

AppModule For DI

package com.shahzaman.weather.weatherFeature.di

import android.app.Application
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.shahzaman.weather.weatherFeature.data.api.WeatherApi
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.create
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    @Provides
    @Singleton
    fun provideWeatherApi(): WeatherApi {
        return Retrofit.Builder()
            .baseUrl("https://api.open-meteo.com/")
            .addConverterFactory(MoshiConverterFactory.create())
            .build()
            .create()
    }

    @Provides
    @Singleton
    fun provideFusedLocationProviderClient(app: Application): FusedLocationProviderClient {
        return LocationServices.getFusedLocationProviderClient(app)
    }
}

Build.gradle

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
}

android {
    namespace 'com.shahzaman.weather'
    compileSdk 34

    defaultConfig {
        applicationId "com.shahzaman.weather"
        minSdk 26
        targetSdk 34
        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 {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    buildFeatures {
        compose true
    }
    composeOptions {
        kotlinCompilerExtensionVersion '1.3.2'
    }
    packagingOptions {
        resources {
            excludes += '/META-INF/{AL2.0,LGPL2.1}'
        }
    }

}

dependencies {

    implementation 'androidx.core:core-ktx:1.10.1'
    implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.0')
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1'
    implementation 'androidx.activity:activity-compose:1.7.2'
    implementation platform('androidx.compose:compose-bom:2022.10.00')
    implementation 'androidx.compose.ui:ui'
    implementation 'androidx.compose.ui:ui-graphics'
    implementation 'androidx.compose.ui:ui-tooling-preview'
    implementation 'androidx.compose.material3:material3'
    implementation 'androidx.wear.compose:compose-material3:1.0.0-alpha07'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
    androidTestImplementation platform('androidx.compose:compose-bom:2022.10.00')
    androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
    debugImplementation 'androidx.compose.ui:ui-tooling'
    debugImplementation 'androidx.compose.ui:ui-test-manifest'


    // Location Services
    implementation 'com.google.android.gms:play-services-location:21.0.1'

    // Retrofit
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-moshi:2.9.0'
    implementation "com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.3"

    //Dagger - Hilt
    implementation 'com.google.dagger:hilt-android:2.46.1'
    annotationProcessor 'com.google.dagger:hilt-compiler:2.46.1'
    implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03'
    implementation 'androidx.hilt:hilt-navigation-compose:1.1.0-alpha01'

    implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1"
}

here is my logcat error message


2023-07-02 12:19:51.558  6775-6804  Finsky                  com.android.vending                  E  [36315] VerifyV31SignatureInstallTask.d(2): VerifyApps V31SignatureVerification: Successful verification for the package: com.shahzaman.weather using APK Signature Scheme v3
2023-07-02 12:19:56.631  7017-7017  AndroidRuntime          pid-7017                             E  FATAL EXCEPTION: main
                                                                                                    Process: com.shahzaman.weather, PID: 7017
                                                                                                    java.lang.RuntimeException: Cannot create an instance of class com.shahzaman.weather.weatherFeature.presentation.WeatherViewModel
                                                                                                        at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:204)
                                                                                                        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:324)
                                                                                                        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:306)
                                                                                                        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:280)
                                                                                                        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.kt:128)
                                                                                                        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:187)
                                                                                                        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:153)
                                                                                                        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:53)
                                                                                                        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:35)
                                                                                                        at com.shahzaman.weather.weatherFeature.presentation.MainActivity.getViewModel(MainActivity.kt:29)
                                                                                                        at com.shahzaman.weather.weatherFeature.presentation.MainActivity.access$getViewModel(MainActivity.kt:26)
                                                                                                        at com.shahzaman.weather.weatherFeature.presentation.MainActivity$onCreate$2$1$1.invoke(MainActivity.kt:62)
                                                                                                        at com.shahzaman.weather.weatherFeature.presentation.MainActivity$onCreate$2$1$1.invoke(MainActivity.kt:54)
                                                                                                        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
                                                                                                        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
                                                                                                        at androidx.compose.material3.SurfaceKt$Surface$1.invoke(Surface.kt:129)
                                                                                                        at androidx.compose.material3.SurfaceKt$Surface$1.invoke(Surface.kt:113)
                                                                                                        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
                                                                                                        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
                                                                                                        at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
                                                                                                        at androidx.compose.material3.SurfaceKt.Surface-T9BRK9s(Surface.kt:110)
                                                                                                        at com.shahzaman.weather.weatherFeature.presentation.MainActivity$onCreate$2$1.invoke(MainActivity.kt:49)
                                                                                                        at com.shahzaman.weather.weatherFeature.presentation.MainActivity$onCreate$2$1.invoke(MainActivity.kt:47)
                                                                                                        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
                                                                                                        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
                                                                                                        at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
                                                                                                        at androidx.compose.material3.TextKt.ProvideTextStyle(Text.kt:261)
                                                                                                        at androidx.compose.material3.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:81)
                                                                                                        at androidx.compose.material3.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:80)
                                                                                                        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
                                                                                                        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
                                                                                                        at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
                                                                                                        at androidx.compose.material3.MaterialThemeKt.MaterialTheme(MaterialTheme.kt:73)
                                                                                                        at com.shahzaman.weather.weatherFeature.presentation.ui.theme.ThemeKt.WeatherTheme(Theme.kt:40)
                                                                                                        at com.shahzaman.weather.weatherFeature.presentation.MainActivity$onCreate$2.invoke(MainActivity.kt:47)
                                                                                                        at com.shahzaman.weather.weatherFeature.presentation.MainActivity$onCreate$2.invoke(MainActivity.kt:46)
                                                                                                        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
                                                                                                        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
                                                                                                        at androidx.compose.ui.platform.ComposeView.Content(ComposeView.android.kt:428)
                                                                                                        at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:252)
                                                                                                        at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:251)
2023-07-02 12:19:56.636  7017-7017  AndroidRuntime          pid-7017                             E      at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7913)
                                                                                                        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:980)
                                                                                                        at android.view.Choreographer.doCallbacks(Choreographer.java:804)
                                                                                                        at android.view.Choreographer.doFrame(Choreographer.java:739)
                                                                                                        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:965)
                                                                                                        at android.os.Handler.handleCallback(Handler.java:883)
                                                                                                        at android.os.Handler.dispatchMessage(Handler.java:100)
                                                                                                        at android.os.Looper.loop(Looper.java:264)
                                                                                                        at android.app.ActivityThread.main(ActivityThread.java:7593)
                                                                                                        at java.lang.reflect.Method.invoke(Native Method)
                                                                                                        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
                                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)
                                                                                                    Caused by: java.lang.NoSuchMethodException: com.shahzaman.weather.weatherFeature.presentation.WeatherViewModel.<init> []
                                                                                                        at java.lang.Class.getConstructor0(Class.java:2332)
                                                                                                        at java.lang.Class.getDeclaredConstructor(Class.java:2170)
                                                                                                        at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:202)
                                                                                                        ... 95 more
2023-07-02 12:19:56.706  1175-1304  InputDispatcher         system_server                        E  channel 'f4f2308 com.shahzaman.weather/com.shahzaman.weather.weatherFeature.presentation.MainActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
2023-07-02 12:46:37.257 14514-14666 Finsky                  com.android.vending                  E  [36585] VerifyV31SignatureInstallTask.d(2): VerifyApps V31SignatureVerification: Successful verification for the package: com.shahzaman.weather using APK Signature Scheme v3
2023-07-02 12:46:42.712 15336-15336 LoadedApk               com.shahzaman.weather                I  No resource references to update in package com.transsion.theme.icon

Upvotes: 0

Views: 206

Answers (2)

AT Amrani
AT Amrani

Reputation: 282

Can you try viewModel() function from lifecycle.lifecycle-viewmodel-compose dependency, like this:

viewModel = viewModel()

Upvotes: 1

Anbalagan D
Anbalagan D

Reputation: 372

Should add provider fun for WeatherRepository, LocationTracker type into AppModule.kt

for example:

@Provides
@Singleton
fun provideWeatherRepository() = WeatherRepository()

Upvotes: 0

Related Questions