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")
}
}