I updated my compose compiler to 1.4.0 so that it works with my kotlin version(1.8.0). Problem is, I had already written my app in compose 1.2.0 . The functions do not work and when I get a prompt to download libraries, they do not download. Now I'm stuck with a half-finished app. This is my Main Activity-
package com.example.notetab
import android.os.Bundle
import android.view.Surface
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import com.example.notetab.ui.theme.NotetabTheme
import org.w3c.dom.Text
import java.lang.reflect.Modifier
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
NotetabTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
topAppBar()
}
}
}
}
}
var username = "MJ"
#Composable
fun topAppBar(){
Column() {
TopAppBar() {
}
}
}
#Preview
#Composable
fun preview() {
Column() {
TopAppBar(
title = {
Text(text = "SemicolonSpace")
}
)
}
}
Here's my gradle-
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
namespace 'com.example.notetab'
compileSdk 33
defaultConfig {
applicationId "com.example.notetab"
minSdk 31
targetSdk 33
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.4.0'
}
packagingOptions {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
implementation 'androidx.activity:activity-compose:1.6.1'
implementation "androidx.compose.ui:ui:$compose_ui_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version"
implementation 'androidx.compose.material:material:1.4.0'
implementation 'androidx.core:core-ktx:+'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_ui_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_ui_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_ui_version"
}
I tried to add new imports but it didn't work. Can somebody help?
Thanks in advance.
I have a problem with Navigation jetpack compose, the problem is navigation doesn't work directly and shows an empty screen, but if I scroll in the empty screen or do a long click after that navigation starts working and shows the screen that I put inside the navigation.
I search a lot about this problem and I don't find any solution.
I try to change the version of the navigation compose and all the versions don't work.
and also when I use dark them work with out problme
except for version "2.4.0-alpha10" which works in some projects and doesn't in some projects
what is the problem? and why does this happen?
build . gradle (Medule:app)
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
namespace 'com.example.myapplication'
compileSdk 33
defaultConfig {
applicationId "com.example.myapplication"
minSdk 24
targetSdk 33
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.9.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.activity:activity-compose:1.5.1'
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'
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'
def nav_version = "2.5.3"
implementation "androidx.navigation:navigation-compose:$nav_version"
}
build . gradle (project)
plugins {
id 'com.android.application' version '8.1.0-alpha02' apply false
id 'com.android.library' version '8.1.0-alpha02' apply false
id 'org.jetbrains.kotlin.android' version '1.7.20' apply false
}
Main Actvity
package com.example.myapplication
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.example.myapplication.ui.theme.MyApplicationTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApplicationTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "younes") {
composable("younes") {
Text(text = "younes")
}
}
}
}
}
}
}
go to the Theme.file and change this line.
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
to
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = true
just change darkTheme to true
When I try to create the ViewModel via viewModel(), I receive the following error:
FATAL EXCEPTION: main
Process: com.github.profit, PID: 23095
java.lang.ClassCastException: java.lang.Object cannot be cast to androidx.lifecycle.ViewModel
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:201)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:322)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:304)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.kt:175)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.kt:138)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:153)
at androidx.lifecycle.viewmodel.compose.ViewModelKt.get(ViewModel.kt:215)
at androidx.lifecycle.viewmodel.compose.ViewModelKt.viewModel(ViewModel.kt:156)
at com.github.profit.MainActivityKt.ProductInfo(MainActivity.kt:136)
at com.github.profit.ComposableSingletons$MainActivityKt$lambda-1$1.invoke(MainActivity.kt:31)
at com.github.profit.ComposableSingletons$MainActivityKt$lambda-1$1.invoke(MainActivity.kt:30)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.material.SurfaceKt$Surface$6.invoke(Surface.kt:268)
at androidx.compose.material.SurfaceKt$Surface$6.invoke(Surface.kt:255)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
at androidx.compose.material.SurfaceKt.Surface-F-jzlyU(Surface.kt:252)
at androidx.compose.material.SurfaceKt.Surface-F-jzlyU(Surface.kt:110)
at com.github.profit.ComposableSingletons$MainActivityKt$lambda-2$1.invoke(MainActivity.kt:27)
at com.github.profit.ComposableSingletons$MainActivityKt$lambda-2$1.invoke(MainActivity.kt:25)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.material.MaterialTheme_androidKt.PlatformMaterialTheme(MaterialTheme.android.kt:23)
at androidx.compose.material.MaterialThemeKt$MaterialTheme$1$1.invoke(MaterialTheme.kt:82)
at androidx.compose.material.MaterialThemeKt$MaterialTheme$1$1.invoke(MaterialTheme.kt:81)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
at androidx.compose.material.TextKt.ProvideTextStyle(Text.kt:265)
at androidx.compose.material.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:81)
at androidx.compose.material.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:80)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
at androidx.compose.material.MaterialThemeKt.MaterialTheme(MaterialTheme.kt:72)
at com.github.profit.ui.theme.ThemeKt.ProfitTheme(Theme.kt:38)
at com.github.profit.ComposableSingletons$MainActivityKt$lambda-3$1.invoke(MainActivity.kt:25)
at com.github.profit.ComposableSingletons$MainActivityKt$lambda-3$1.invoke(MainActivity.kt:24)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
My application looks like this:
MainActivity
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ProfitTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
ProductInfo()
}
}
}
}
}
ProductInfo
#Composable
fun ProductInfo() {
val viewModel: ProductsViewModel by viewModel()
Column {
TextField(
value = viewModel.product1Price,
onValueChange = {
viewModel.product1Price = it
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
label = { Text(text = "Price") },
placeholder = { Text(text = "Price in Ft") },
)
// ...
}
}
ProductsViewModel
class ProductsViewModel: ViewModel() {
private val _product1Price = mutableStateOf(0U)
private val _product1Quantity = mutableStateOf(0U)
private val _product2Price = mutableStateOf(0U)
private val _product2Quantity = mutableStateOf(0U)
var product1Price: String
get() = _product1Price.value.toString()
set(value) = setField(_product1Price, value)
// ...
}
My project build.gradle
buildscript {
ext {
compose_ui_version = '1.1.1'
lifecycle_version = '2.5.1'
}
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.3.1' apply false
id 'com.android.library' version '7.3.1' apply false
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}
The app's build.gradle:
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
namespace 'com.github.profit'
compileSdk 32
defaultConfig {
applicationId "com.github.profit"
minSdk 22
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 {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion '1.1.1'
}
packagingOptions {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
}
dependencies {
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.activity:activity-compose:1.3.1'
implementation "androidx.compose.ui:ui:$compose_ui_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version"
implementation 'androidx.compose.material:material:1.1.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_ui_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_ui_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_ui_version"
}
You can create a view model in compose like like,
val viewModel = viewModel<ProductsViewModel>()
or
val viewModel: ProductsViewModel = viewModel()
For more info refer this codelab.
I have been following a tutorial from Geeks for Geeks on how to make a simple note app for Android. I've practically copied to code word-by-word (except for a minor fix in the gradle file as advised from a Stack Overflow post and a comment in the YouTube comment section), yet the app crashes every time I open it even after clearing all the caches and rebuilding the project.
Links:
https://www.geeksforgeeks.org/how-to-build-a-simple-note-android-app-using-mvvm-and-room-database/
https://www.youtube.com/watch?v=D2F5t-phP04
Now, I know the problem with the code stems from the below command line.
viewModel = ViewModelProvider(
this,
ViewModelProvider.AndroidViewModelFactory.getInstance(application)
).get(NoteViewModel::class.java)
Every time I include the above line and launch the app, the app crashes, and my phone cannot open it. Commenting out the above line and the code below it allows the app to be opened without an issue.
(App gradle)
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.notepractice"
minSdk 26
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
}
packagingOptions {
exclude 'META-INF/atomicfu.kotlin_module'
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
}
}
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)
implementation 'androidx.fragment:fragment-ktx:1.1.0'
// Room components
implementation "androidx.room:room-ktx:$rootProject.roomVersion"
annotationProcessor "androidx.room:room-compiler:$rootProject.roomVersion"
androidTestImplementation "androidx.room:room-testing:$rootProject.roomVersion"
// Lifecycle components
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
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"
// 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"
}
(Project gradle)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.5.31"
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle-api:7.2.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
plugins {
id 'com.android.application' version '7.2.0' apply false
id 'com.android.library' version '7.2.0' apply false
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
}
allprojects {
repositories {
google()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
/*
ext {
activityVersion = '1.4.0'
appCompatVersion = '1.4.0'
constraintLayoutVersion = '2.1.2'
coreTestingVersion = '2.1.0'
coroutines = '1.5.2'
lifecycleVersion = '2.4.0'
materialVersion = '1.4.0'
roomVersion = '2.3.0'
// testing
junitVersion = '4.13.2'
espressoVersion = '3.4.0'
androidxJunitVersion = '1.1.3'
}
*/
ext {
activityVersion = '1.2.3'
appCompatVersion = '1.3.0'
constraintLayoutVersion = '2.0.4'
coreTestingVersion = '2.1.0'
coroutines = '1.5.0'
lifecycleVersion = '2.3.1'
materialVersion = '1.3.0'
roomVersion = '2.3.0'
// testing
junitVersion = '4.13.2'
espressoVersion = '3.1.0'
androidxJunitVersion = '1.1.2'
}
(Main Activity)
package com.example.notepractice
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.floatingactionbutton.FloatingActionButton
import java.util.*
class MainActivity : AppCompatActivity(), NoteClickInterface, NoteClickDeleteInterface {
lateinit var viewModel: NoteViewModel
lateinit var notesRV: RecyclerView
lateinit var addFAB: FloatingActionButton
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
notesRV = findViewById(R.id.RVNotes)
addFAB = findViewById(R.id.FABAddNote)
notesRV.layoutManager = LinearLayoutManager(this)
val noteRVAdapter = NoteRVAdapter(this, this, this)
notesRV.adapter = noteRVAdapter
viewModel = ViewModelProvider(
this,
ViewModelProvider.AndroidViewModelFactory.getInstance(application)
).get(NoteViewModel::class.java)
/*
viewModel.allNotes.observe(this, Observer { list ->
list?.let {
noteRVAdapter.updateList(it)
}
})
addFAB.setOnClickListener {
val intent = Intent(this#MainActivity, AddEditNoteActivity::class.java)
startActivity(intent)
this.finish()
}
*/
}
override fun onNoteClick(note: Note) {
val intent = Intent(this#MainActivity, AddEditNoteActivity::class.java)
intent.putExtra("noteType", "Edit")
intent.putExtra("noteTitle", note.noteTitle)
intent.putExtra("noteDescription", note.noteDescription)
intent.putExtra("noteId", note.id)
startActivity(intent)
}
override fun onDeleteIconClick(note: Note) {
viewModel.deleteNote(note)
Toast.makeText(this, "${note.noteTitle} Deleted", Toast.LENGTH_LONG).show()
}
}
(ViewModel)
package com.example.notepractice
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class NoteViewModel(application: Application): AndroidViewModel(application) {
val allNotes: LiveData<List<Note>>
val repository: NoteRepository
init {
val dao = NoteDatabase.getDatabase(application).getNotesDao()
repository = NoteRepository(dao)
allNotes = repository.allNotes
}
fun deleteNote (note: Note) = viewModelScope.launch(Dispatchers.IO) {
repository.delete(note)
}
fun updateNote(note: Note) = viewModelScope.launch(Dispatchers.IO) {
repository.update(note)
}
fun addNote(note: Note) = viewModelScope.launch(Dispatchers.IO) {
repository.insert(note)
}
}
I'd like to end my question post with an actual question, but I am very inexperienced and cannot specify the problem. What would be the correct way to set up a ViewModel in Android with Kotlin?
Try initialising NoteViewModel like this inside your Activity.
private val viewModel: NoteViewModel by lazy {
ViewModelProvider(this).get(NoteViewModel::class.java)
}
I am trying to run instrumented tests for my fragments and appears nothing works
the result shows nothing no pass no errors nothing
like this answer :answer link
I tried unchecking the run instrumented test with Gradle
put the result is nothing :
tests result
and when checking it : throws exception
"Run Android instrumented tests using Gradle" option was ignored because this module type is not supported yet.
"
and yet no results
test results2
my project gradle:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlinVersion = '1.3.72'
ext.navigationVersion = '2.4.1'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigationVersion"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
ext {
// Sdk and tools
// Support library and architecture components support minSdk 14 and above.
minSdkVersion = 21
targetSdkVersion = 30
compileSdkVersion = 31
// App dependencies
androidXVersion = '1.0.0'
androidXAnnotations = '1.0.1'
androidXLegacySupport = '1.0.0'
appCompatVersion = '1.2.0'
archLifecycleVersion = '2.2.0'
cardVersion = '1.0.0'
materialVersion = '1.1.0'
fragmentVersion = '1.1.0-alpha07'
recyclerViewVersion = '1.1.0'
mockitoVersion = '2.8.9'
constraintVersion = '2.0.0-rc1'
dexMakerVersion = '2.12.1'
coroutinesVersion = '1.2.1'
roomVersion = '2.4.2'
koinVersion = '2.0.1'
truthVersion = '0.44'
junitVersion = '4.12'
androidXTestCoreVersion = '1.2.0-beta01'
robolectricVersion = '4.3-beta-1'
androidXTestExtKotlinRunnerVersion = '1.1.1'
archTestingVersion = '2.0.0'
playServicesVersion = '17.0.0'
hamcrestVersion = '1.3'
androidXTestRulesVersion = '1.2.0-beta01'
espressoVersion = '3.2.0'
}
app gradle:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
apply plugin: "androidx.navigation.safeargs.kotlin"
android {
compileSdkVersion rootProject.compileSdkVersion
defaultConfig {
applicationId "com.mostafan3ma.android.pcm_helper10"
minSdkVersion rootProject.minSdkVersion
targetSdkVersion rootProject.targetSdkVersion
versionCode 1
versionName "1.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
kotlinOptions {
jvmTarget = "1.8"
}
testOptions.unitTests {
includeAndroidResources = true
returnDefaultValues = true
}
buildFeatures {
viewBinding = true
dataBinding = true
}
}
dependencies {
implementation "androidx.appcompat:appcompat:$appCompatVersion"
implementation "com.google.android.material:material:$materialVersion"
implementation "androidx.constraintlayout:constraintlayout:$constraintVersion"
implementation "androidx.navigation:navigation-fragment-ktx:$navigationVersion"
implementation "androidx.navigation:navigation-ui-ktx:$navigationVersion"
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation "androidx.annotation:annotation:$androidXAnnotations"
kapt "androidx.lifecycle:lifecycle-compiler:$archLifecycleVersion"
implementation "androidx.lifecycle:lifecycle-extensions:$archLifecycleVersion"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$archLifecycleVersion"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$archLifecycleVersion"
//Room dependencies
implementation("androidx.room:room-runtime:$roomVersion")
annotationProcessor("androidx.room:room-compiler:$roomVersion")
kapt("androidx.room:room-compiler:$roomVersion")
implementation("androidx.room:room-ktx:$roomVersion")
implementation 'com.google.code.gson:gson:2.8.6'
implementation "com.google.android.gms:play-services-location:$playServicesVersion"
implementation "com.google.android.gms:play-services-maps:$playServicesVersion"
//floating action button
implementation 'com.getbase:floatingactionbutton:1.10.1'
//xls files api
implementation 'org.apache.poi:poi:3.17'
// Dependencies for local unit tests
testImplementation "junit:junit:$junitVersion"
testImplementation "androidx.test:core-ktx:$androidXTestCoreVersion"
testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion"
// Dependencies for Android instrumented unit tests
androidTestImplementation "junit:junit:$junitVersion"
androidTestImplementation "org.mockito:mockito-core:$mockitoVersion"
androidTestImplementation "com.linkedin.dexmaker:dexmaker-mockito:$dexMakerVersion"
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion"
androidTestImplementation "androidx.arch.core:core-testing:$archTestingVersion"
//Robolectric and AndroidX test Dependencies
testImplementation "androidx.test:core-ktx:$androidXTestCoreVersion"
testImplementation "org.robolectric:robolectric:$robolectricVersion"
"androidx.test.ext:junit-ktx:$androidXTestExtKotlinRunnerVersion"
testImplementation "androidx.arch.core:core-testing:$archTestingVersion"
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion"
// AndroidX Test - Instrumented testing
androidTestImplementation "androidx.test.ext:junit:$androidXTestExtKotlinRunnerVersion"
androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion"
androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion"
implementation "androidx.test.espresso:espresso-idling-resource:$espressoVersion"
implementation "androidx.fragment:fragment-testing:$fragmentVersion"
implementation "androidx.test:core:$androidXTestCoreVersion"
}
I am using ServiceLocater to inject repository into fragments
ServiceLocater.kt:
package com.mostafan3ma.android.pcm_helper10
import android.content.Context
import androidx.annotation.VisibleForTesting
import androidx.room.Room
import com.mostafan3ma.android.pcm_helper10.data.source.DefaultLocalDataSource
import com.mostafan3ma.android.pcm_helper10.data.source.LocalDataSource.LocalDataSource
import com.mostafan3ma.android.pcm_helper10.data.source.PipeLinesRepository
import com.mostafan3ma.android.pcm_helper10.data.source.database.LineDataBase
import kotlinx.coroutines.runBlocking
object ServiceLocator {
private var dataBase:LineDataBase?=null
#Volatile
var pipeLinesRepository: PipeLinesRepository?=null
#VisibleForTesting set
private val lock=Any()
fun provideRepository(context: Context):PipeLinesRepository{
synchronized(this){
return pipeLinesRepository?:createPipeLineRepository(context)
}
}
private fun createPipeLineRepository(context: Context): PipeLinesRepository {
val newRepo=PipeLinesRepository(createLocalDataSource(context))
pipeLinesRepository=newRepo
return newRepo
}
private fun createLocalDataSource(context: Context): DefaultLocalDataSource {
val dataBase= dataBase?:createDatabase(context)
return LocalDataSource(dataBase.lineDao())
}
private fun createDatabase(context: Context): LineDataBase {
val result= Room.databaseBuilder(
context.applicationContext,
LineDataBase::class.java,
"Lins"
).fallbackToDestructiveMigration().build()
dataBase=result
return result
}
#VisibleForTesting
fun resetRepo(){
synchronized(lock){
runBlocking {
pipeLinesRepository?.clearAllLines()
}
dataBase?.apply {
clearAllTables()
close()
}
dataBase=null
pipeLinesRepository=null
}
}
}
and the test class for one of the fragments :
package com.mostafan3ma.android.pcm_helper10.lines
import android.os.Bundle
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.fragment.app.testing.launchFragmentInContainer
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
import com.mostafan3ma.android.pcm_helper10.R
import com.mostafan3ma.android.pcm_helper10.ServiceLocator
import com.mostafan3ma.android.pcm_helper10.Utils.FakeDataSource
import com.mostafan3ma.android.pcm_helper10.Utils.MainCoroutineRule
import com.mostafan3ma.android.pcm_helper10.data.source.PipeLinesRepository
import com.mostafan3ma.android.pcm_helper10.data.source.database.DamagePoint
import com.mostafan3ma.android.pcm_helper10.data.source.database.PipeLine
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Assert.*
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
#MediumTest
#RunWith(AndroidJUnit4::class)
#ExperimentalCoroutinesApi
class MainLinesFragmentTest {
private val initList = mutableListOf<PipeLine>(
PipeLine(
id = 1,
name = "line1",
ogm = "1",
length = "1000",
type = "Water",
i_start = "1000",
i_end = "10",
start_point_x = "511511",
start_point_y = "3591511",
end_point_x = "511511",
end_point_y = "3591511",
start_work_date = "2/5/2022",
end_work_date = "3/5/2022",
work_team = "Mostafa Nema 1",
input = "1A",
extra_note = "note1",
points = mutableListOf<DamagePoint>(
DamagePoint(
no = 1, db = "11", depth = "1.1",
current1 = "111", current2 = "122",
gps_x = "511511", gps_y = "35911511",
note = "point note1", is_point = true
),
DamagePoint(
no = 2, db = "22", depth = "2.2",
current1 = "211", current2 = "222",
gps_x = "511511", gps_y = "35911511",
note = "point note2", is_point = true
),
DamagePoint(is_point = false),
DamagePoint(
no = 3, db = "33", depth = "3.1",
current1 = "311", current2 = "322",
gps_x = "511511", gps_y = "35911511",
note = "point note3", is_point = true
)
)
),
PipeLine(
id = 2,
name = "line2",
ogm = "2",
length = "2000",
type = "oil",
i_start = "2000",
i_end = "20",
start_point_x = "522522",
start_point_y = "3591522",
end_point_x = "522522",
end_point_y = "3591522",
start_work_date = "2/5/2022",
end_work_date = "3/5/2022",
work_team = "Mostafa Nema 2",
input = "2A",
extra_note = "note2",
points = mutableListOf<DamagePoint>(
DamagePoint(
no = 1, db = "11", depth = "1.1",
current1 = "111", current2 = "122",
gps_x = "511511", gps_y = "35911511",
note = "point note1", is_point = true
)
)
)
)
private lateinit var localDataSource: FakeDataSource
private lateinit var repository: PipeLinesRepository
#get:Rule
val mainCoroutineRule = MainCoroutineRule()
#get:Rule
var instantExecutorRule= InstantTaskExecutorRule()
#Before
fun setUp() {
localDataSource = FakeDataSource(initList)
repository=PipeLinesRepository(localDataSource,Dispatchers.Main)
ServiceLocator.pipeLinesRepository=repository
}
#After
fun tearDown() {
ServiceLocator.resetRepo()
}
#Test
fun displayFragment_TwoPipeInList()=mainCoroutineRule.runBlockingTest {
launchFragmentInContainer<MainLinesFragment>(Bundle(), R.style.Theme_Pcmhelper10)
onView(withId(R.id.fab_add_line)).check(matches(isDisplayed()))
}
}
and I got this exception which didn't understand !!
2022-06-07 00:12:34.950 6305-6325/com.mostafan3ma.android.pcm_helper10 E/AndroidRuntime: FATAL EXCEPTION: Instr: androidx.test.runner.AndroidJUnitRunner
Process: com.mostafan3ma.android.pcm_helper10, PID: 6305
java.lang.NoSuchMethodError: No virtual method shouldWaitForActivitiesToComplete()Z in class Landroidx/test/runner/AndroidJUnitRunner; or its super classes (declaration of 'androidx.test.runner.AndroidJUnitRunner' appears in /data/app/~~4CMeGrOsgkmvqLHECyOCZw==/com.mostafan3ma.android.pcm_helper10.test-N5A3R_1QMgwrtEkdIr0X8Q==/base.apk)
at androidx.test.runner.AndroidJUnitRunner.addListenersLegacyOrder(AndroidJUnitRunner.java:490)
at androidx.test.runner.AndroidJUnitRunner.addListeners(AndroidJUnitRunner.java:471)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:443)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2248)
REPLACE
testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion"
WITH
testImplementation 'org.hamcrest:hamcrest:2.2'
testImplementation 'org.hamcrest:hamcrest-library:2.2'