Reputation: 157
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
Reputation: 282
Can you try viewModel() function from lifecycle.lifecycle-viewmodel-compose dependency, like this:
viewModel = viewModel()
Upvotes: 1
Reputation: 372
Should add provider fun for WeatherRepository, LocationTracker type into AppModule.kt
for example:
@Provides
@Singleton
fun provideWeatherRepository() = WeatherRepository()
Upvotes: 0