大家好,我目前正在做一些小项目,使用Jetpack Compose和线圈依赖来显示viewModel中的图像,但我的应用程序有一个这样的错误:
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)
我已try 更改为新版本的Coil Dependents,但仍出现错误
这是我的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))
}
}
我希望有谁能帮我找到这个问题的解决办法,谢谢