I'm trying to call the await() function in the
bookList = bookViewModel.getBookList().await()
in the Main Activity but it gives the error in the header.
Main Activity
#AndroidEntryPoint
class MainActivity : ComponentActivity() {
private val bookViewModel: BookViewModel by viewModels()
private var bookList : BookList? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GlobalScope.launch(Dispatchers.IO) {
bookList = bookViewModel.getBookList().await()
}
setContent {
LOTRAppTheme {
}
}
}
}
ViewModel
package com.example.lotrapp
import androidx.lifecycle.ViewModel
import com.example.lotrapp.models.BookList
import com.example.lotrapp.repository.BookRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
#HiltViewModel
class BookViewModel #Inject constructor(
private val repository: BookRepository
) : ViewModel() {
suspend fun getBookList() : BookList? {
return repository.getBookList()
}
}
Repository
package com.example.lotrapp.repository
import com.example.lotrapp.models.BookList
import com.example.lotrapp.network.RetrofitApi
import javax.inject.Inject
class BookRepository #Inject constructor(
private val retrofitApi: RetrofitApi
) {
suspend fun getBookList() : BookList?
{
return retrofitApi.getBookList().body()
}
}
Api
package com.example.lotrapp.network
import com.example.lotrapp.models.BookList
import retrofit2.Response
import retrofit2.http.GET
interface RetrofitApi {
#GET("book")
suspend fun getBookList() : Response<BookList>
}
Gradle:
plugins {
id 'com.android.application'
id 'kotlin-android'
id("dagger.hilt.android.plugin")
id("kotlin-kapt")
}
android {
compileSdk 31
defaultConfig {
applicationId "com.example.lotrapp"
minSdk 21
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 {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
useIR = true
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion compose_version
kotlinCompilerVersion '1.5.10'
}
packagingOptions {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
}
dependencies {
def compose_version = "1.0.2"
def lifecycle_version = "2.3.1"
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.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation "androidx.compose.runtime:runtime-livedata:$compose_version"
// ViewModel
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
// LiveData
implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")
// Lifecycles only (without ViewModel or LiveData)
implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version")
// Saved state module for ViewModel
implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version")
// Annotation processor
kapt("androidx.lifecycle:lifecycle-compiler:$lifecycle_version")
// alternately - if using Java8, use the following instead of lifecycle-compiler
implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycle_version")
implementation 'androidx.activity:activity-compose:1.3.1'
testImplementation 'junit:junit:4.+'
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"
//Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
//Hilt
implementation("com.google.dagger:hilt-android:2.38.1")
kapt("com.google.dagger:hilt-android-compiler:2.38.1")
//Coroutines
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2")
}
kapt {
correctErrorTypes true
}
First I want to pull the list from the api and then show it in the UI with a Composable function (with LazyColumn) in setContent. It is enough to solve this error, but if you have better code suggestions, I would appreciate it. Thank you!
It doesn't really seem you need to invoke await() there. getBookList() returns BookList? directly, so just remove await() and it should be fine.
Additionally, you said you need to use this bookList in setContent. In that case you need to move setContent into launch block, below getBookList(). Right now setContent really executes before bookList is acquired. It is hard to provide more details without the full contents of setContent.
Related
Learning Unit testing on android, my tests are not running now, says "Test events were not received, not much details on the stack trace I tried adding and removing some dependencies but did not worked. looked into some other stackoverflow results still not working, I am doing this by following a udemy course on TDD.
Here is one of my test classes
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runBlockingTest
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test
import org.mockito.kotlin.mock
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import petros.efthymiou.groovy.utils.BaseUnitTest
import petros.efthymiou.groovy.utils.getValueForTest
class PlayListViewModelShould:BaseUnitTest() {
private val repository: PlayListRepository = mock()
private val playList = mock<List<PlayList>>()
private val expected = Result.success(playList)
private val exception = java.lang.RuntimeException("SOMETHING NOT RIGHT")
#OptIn(ExperimentalCoroutinesApi::class)
#Test
suspend fun getPlaylistsFromRepository()= runTest{
val viewModel = mockSuccesfulCase()
viewModel.playlists.getValueForTest()
verify(repository,times(1)).getPlaylists()
}
#OptIn(ExperimentalCoroutinesApi::class)
#Test
fun emitPlaylistsFromRepository()= runTest {
val viewModel = mockSuccesfulCase()
assertEquals(expected, viewModel.playlists.getValueForTest())
}
#OptIn(ExperimentalCoroutinesApi::class)
#Test
fun emitErrorWhenRecieveError() {
runTest {
whenever(repository.getPlaylists()).thenReturn(
flow {
emit(Result.failure<List<PlayList>>(exception))
}
)
}
val viewModel = PlayListViewModel(repository)
assertEquals(java.lang.RuntimeException("another error"), viewModel.playlists.getValueForTest()!!.exceptionOrNull())
}
private fun mockSuccesfulCase(): PlayListViewModel {
runBlocking {
whenever(repository.getPlaylists()).thenReturn(
flow {
emit(expected)
}
)
}
return PlayListViewModel(repository)
}
}
My gradle
android {
compileSdkVersion 30
defaultConfig {
applicationId "petros.efthymiou.groovy"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
testOptions {
execution 'ANDROIDX_TEST_ORCHESTRATOR'
unitTests.all {
useJUnitPlatform()
}
}
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'
freeCompilerArgs = freeCompilerArgs + "-Xallow-result-return-type"
}
testOptions {
animationsDisabled = true
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.0-alpha04'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'com.jakewharton.espresso:okhttp3-idling-resource:1.0.0'
// testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0'
testImplementation 'org.mockito:mockito-inline:2.21.0'
testImplementation 'androidx.arch.core:core-testing:2.1.0'
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.8'
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.9.1")
testImplementation 'org.mockito.kotlin:mockito-kotlin:4.0.0'
testImplementation "org.mockito:mockito-core:4.3.1"
androidTestImplementation "org.mockito:mockito-android:3.10.0"
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.1'
testImplementation 'org.junit.vintage:junit-vintage-engine:5.9.1'
androidTestImplementation 'com.jakewharton.espresso:okhttp3-idling-resource:1.0.0'
androidTestImplementation 'androidx.test:runner:1.5.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation "org.mockito:mockito-core:4.3.1"
androidTestImplementation 'junit:junit:4.13.2'
androidTestImplementation "org.robolectric:robolectric:4.3.1"
androidTestImplementation('com.schibsted.spain:barista:3.6.0') {
exclude group: 'org.jetbrains.kotlin' // Only if you already use Kotlin in your project
}
}
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'm new learning Kotlin and I'm developing a Notes app to practise with databases and viewModels.
I'm having trouble generating my database and the app crashes when it should generate the database and shows me this error on the logcat:
"java.lang.RuntimeException: cannot find implementation for com.example.blocnotas.database.AppDatabase. AppDatabase_Impl does not exist"
This is how I made my Database class:
package com.example.blocnotas.database
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
#Database(entities = [Notes::class], version = 1, exportSchema = false)
abstract class AppDatabase: RoomDatabase() {
abstract fun noteDao(): NoteDao
companion object {
#Volatile
private var INSTANCE: AppDatabase? = null
fun getDatabase(context: Context): AppDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"app_notes_database")
.build()
INSTANCE = instance
return instance
}
}
}
My Application class:
package com.example.blocnotas
import android.app.Application
import com.example.blocnotas.database.AppDatabase
class NotesApplication : Application() {
val database: AppDatabase by lazy { AppDatabase.getDatabase(this) }
}
My app gradle:
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
//id 'androidx.navigation.safeargs.kotlin'
}
android {
namespace 'com.example.blocnotas'
compileSdk 32
defaultConfig {
applicationId "com.example.blocnotas"
minSdk 19
targetSdk 32
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 {
viewBinding true
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.navigation:navigation-fragment-ktx:2.5.2'
implementation 'androidx.navigation:navigation-ui-ktx:2.5.2'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
// optional - Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"
}
Does anybody know how can i fix it and generate my database table?
I leave you the gitHub repository where i'm making it so if it can help get any extra necessary information: https://github.com/R3inbow/BlocNotasApp.git
I finally solved it changing in the gradle the "kapt" for "ksp" this way:
In dependencies:
ksp "androidx.room:room-compiler:$room_version"
In plugins:
id 'com.google.devtools.ksp' version '1.7.20-1.0.6'
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
I am trying to call a suspend function using viewModelScope.launch in which "launch" is showing as Unresolved reference.
Here is build.gradle
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
}
android {
compileSdk 31
defaultConfig {
applicationId "com.example.mynotes"
minSdk 27
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'
}
packagingOptions {
exclude 'META-INF/atomicfu.kotlin_module'
}
}
dependencies {
implementation "androidx.appcompat:appcompat:$rootProject.appCompatVersion"
implementation "androidx.activity:activity-ktx:$rootProject.activityVersion"
// Dependencies for working with Architecture components
// You'll probably have to update the version numbers in build.gradle (Project)
// Room components
implementation "androidx.room:room-ktx:$rootProject.roomVersion"
kapt "androidx.room:room-compiler:$rootProject.roomVersion"
androidTestImplementation "androidx.room:room-testing:$rootProject.roomVersion"
// Lifecycle components
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$rootProject.lifecycleVersion"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$rootProject.lifecycleVersion"
implementation "androidx.lifecycle:lifecycle-common-java8:$rootProject.lifecycleVersion"
// Kotlin components
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$rootProject.coroutines"
api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$rootProject.coroutines"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0'
// UI
implementation "androidx.constraintlayout:constraintlayout:$rootProject.constraintLayoutVersion"
implementation "com.google.android.material:material:$rootProject.materialVersion"
// Testing
testImplementation "junit:junit:$rootProject.junitVersion"
androidTestImplementation "androidx.arch.core:core-testing:$rootProject.coreTestingVersion"
androidTestImplementation ("androidx.test.espresso:espresso-core:$rootProject.espressoVersion", {
exclude group: 'com.android.support', module: 'support-annotations'
})
androidTestImplementation "androidx.test.ext:junit:$rootProject.androidxJunitVersion"
}
and the ViewModel.kt
package com.example.mynotes
import android.app.Application
//import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.*
class NotesViewModel(application: Application) : ViewModel() {
private val repository : NotesRepository
val allNotes : LiveData<List<Notes>>
init {
val dao = NotesDatabase.getDatabase(application).getNotesDao()
repository = NotesRepository(dao)
allNotes = repository.allNotes
}
fun deleteNotes(notes: Notes) = viewModelScope.launch(Dispatchers.IO) {
repository.delete(notes)
}
}
In the function deleteNotes "viewModelScope.launch" is showing Unresolved reference: launch but there is no error while building the app but my app crash while running.
I think it's because of the way you are declaring the variable, since you are declaring it as a direct function, you can try the following:
fun deleteNotes(notes: Notes) {
viewModelScope.launch(Dispatchers.IO) {
repository.delete(notes)
}
}
It's possible the issue is related that when the method is declared and stored in memory, the scope hasnt been assigned yet.
Which version are you using?
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
Try to use this case is different.
Try to invalide cache and restart if still not recognized