I am working on a project using Jetpack Compose and Coil dependency to displaying image from viewModel, but my app shows an error like this:
No interface method startRestartGroup(ILjava/lang/String;)Landroidx/compose/runtime/Composer; in class Landroidx/compose/runtime/Composer; or its super classes (declaration of 'androidx.compose.runtime.Composer'
....
at com.google.accompanist.coil.CoilImage__CoilKt.CoilImage(Coil.kt:324)
at com.google.accompanist.coil.CoilImage.CoilImage(Coil.kt:1)
at PokemonListScreenKt.PokedexEntry(PokemonListScreen.kt:172)
at PokemonListScreenKt.PokedexRow(PokemonListScreen.kt:212)
at PokemonListScreenKt$PokemonList$1$1.invoke(PokemonListScreen.kt:136)
at PokemonListScreenKt$PokemonList$1$1.invoke(PokemonListScreen.kt:132)
I have tried to change to the new version of Coil dependencies, but the error still occurs.
Here is my build.gradle (app)
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-android'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}
android {
namespace 'com.example.pokedex'
compileSdk 34
defaultConfig {
applicationId "com.example.pokedex"
minSdk 24
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_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion '1.4.6'
}
packagingOptions {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.8.0'
implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.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'
implementation 'com.google.android.material:material:1.3.0'
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'
implementation "androidx.compose.material:material-icons-core:1.5.4"
implementation "androidx.compose.material:material-icons-extended:1.5.4"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0-beta01"
implementation "androidx.navigation:navigation-compose:2.7.5"
implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13"
// Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation "com.squareup.okhttp3:okhttp:4.11.0"
implementation "com.squareup.okhttp3:logging-interceptor:4.9.0"
// Timber
implementation 'com.jakewharton.timber:timber:4.7.1'
// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3'
// Coroutine Lifecycle Scopes
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.3.1"
// Coil
implementation "io.coil-kt:coil-compose:2.5.0"
// implementation("io.coil-kt:coil-compose:1.3.2")
//Dagger - Hilt
kapt "androidx.hilt:hilt-compiler:1.1.0"
kapt("org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0")
//Dagger - Hilt
implementation "com.google.dagger:hilt-android:2.44"
kapt "com.google.dagger:hilt-compiler:2.44"
implementation 'androidx.hilt:hilt-navigation-compose:1.1.0'
kapt("org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0")
// Palette
implementation 'androidx.palette:palette-ktx:1.0.0'
}
// PokemonListScreen.kt
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.Center
import androidx.compose.ui.Alignment.Companion.CenterHorizontally
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.scale
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.focus.FocusState
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import coil.compose.SubcomposeAsyncImage
import coil.request.ImageRequest
import com.example.pokedex.R
import com.example.pokedex.data.models.PokedexListEntry
import com.example.pokedex.pokemonList.PokemonListViewModel
import com.example.pokedex.ui.theme.RobotoCondensed
@Composable
fun PokemonListScreen(
navController: NavController
) {
Surface(
color = MaterialTheme.colorScheme.background,
modifier = Modifier.fillMaxSize()
) {
Column {
Spacer(modifier = Modifier.height(20.dp))
Image(
painter = painterResource(id = R.drawable.ic_international_pok_mon_logo),
contentDescription = "Pokemon",
modifier = Modifier
.fillMaxWidth()
.align(CenterHorizontally)
)
SearchBar(
hint = "Search...",
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
}
Spacer(modifier = Modifier.height(16.dp))
PokemonList(navController = navController)
}
}
}
@Composable
fun SearchBar(
modifier: Modifier = Modifier,
hint: String = "",
onSearch: (String) -> Unit = {}
) {
var text by remember {
mutableStateOf("")
}
var isHintDisplayed by remember {
mutableStateOf(hint != "")
}
Box(modifier = modifier) {
BasicTextField(
value = text,
onValueChange = {
text = it
onSearch(it)
},
maxLines = 1,
singleLine = true,
textStyle = TextStyle(color = Color.Black),
modifier = Modifier
.fillMaxWidth()
.shadow(5.dp, CircleShape)
.background(Color.White, CircleShape)
.padding(horizontal = 20.dp, vertical = 12.dp)
.onFocusChanged {
isHintDisplayed = it != FocusState::isFocused
}
)
if (isHintDisplayed) {
Text(
text = hint,
color = Color.LightGray,
modifier = Modifier
.padding(horizontal = 20.dp, vertical = 12.dp)
)
}
}
}
@Composable
fun PokemonList(
navController: NavController,
viewModel: PokemonListViewModel = hiltViewModel()
) {
val pokemonList by remember { viewModel.pokemonList }
val endReached by remember { viewModel.endReached }
val loadError by remember { viewModel.loadError }
val isLoading by remember { viewModel.isLoading }
LazyColumn(contentPadding = PaddingValues(16.dp)) {
val itemCount = if(pokemonList.size % 2 == 0) {
pokemonList.size / 2
} else {
pokemonList.size / 2 + 1
}
items(itemCount) {
if(it >= itemCount && !endReached) {
viewModel.loadPokemonPaginated()
}
PokedexRow(rowIndex = it, entries = pokemonList, navController = navController)
}
}
}
@Composable
fun PokedexEntry(
entry: PokedexListEntry,
navController: NavController,
modifier: Modifier = Modifier,
viewModel: PokemonListViewModel = hiltViewModel()
) {
val defaultDominantColor = MaterialTheme.colorScheme.surface
var dominantColor by remember {
mutableStateOf(defaultDominantColor)
}
Box(
contentAlignment = Center,
modifier = modifier
.shadow(5.dp, RoundedCornerShape(10.dp))
.clip(RoundedCornerShape(10.dp))
.aspectRatio(1f)
.background(
Brush.verticalGradient(
listOf(
dominantColor,
defaultDominantColor
)
)
)
.clickable {
navController.navigate("pokemon_detail_screen/${dominantColor.toArgb()}/${entry.pokemonName}")
}
) {
Column {
SubcomposeAsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(entry.imageUrl)
.target {
viewModel.calcDominantColor(it) { color ->
dominantColor = color
}
}
.crossfade(true)
.build(),
contentDescription = entry.pokemonName,
modifier = Modifier
.size(120.dp)
.align(CenterHorizontally)
) {
CircularProgressIndicator(
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.scale(0.5f)
)
}
Text(
text = entry.pokemonName,
fontFamily = RobotoCondensed,
fontSize = 20.sp,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
}
}
}
@Composable
fun PokedexRow(
rowIndex: Int,
entries: List<PokedexListEntry>,
navController: NavController
) {
Column {
Row {
PokedexEntry(
entry = entries[rowIndex * 2],
navController = navController,
modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.width(16.dp))
if (entries.size >= rowIndex * 2 + 2) {
PokedexEntry(
entry = entries[rowIndex * 2 + 1],
navController = navController,
modifier = Modifier.weight(1f)
)
} else {
Spacer(modifier = Modifier.weight(1f))
}
}
Spacer(modifier = Modifier.height(16.dp))
}
}
It looks like you're using Accompanist's Coil integration. This has been replaced by Coil's first party integration and its AsyncImage
composable. It's likely Accompanist's Coil integration doesn't work with the latest Compose version as it's no longer supported. Try using implementation("io.coil-kt:coil-compose:2.5.0")
and replace usages of CoilImage
with AsyncImage
.