Я работаю над проектом Android, используя Jetpack Compose для создания приложения со списком фильмов. Я хочу обновить posterPath определенного элемента в LazyVerticalGrid без перекомпоновки всего списка. Однако когда я нажимаю на элемент, весь список перестраивается. Ниже мой код:
Код: Выделить всё
@Composable
fun MovieItem(movie: Movie, position: Int, onClick: (Int) -> Unit) {
Rebugger(trackMap = mapOf("movie" to movie, "onClick" to onClick))
Box(
modifier = Modifier
.padding(5.dp)
.border(2.dp, Color.Black, customBorderShape)
.background(Color.White, customShape)
.height(200.dp)
.clip(customShape)
.clickable { onClick(position) }
) {
GetImage(
movie.posterPath,
modifier = Modifier
.align(Alignment.Center)
.fillMaxSize()
.scale(1.8f)
.aspectRatio(1f)
)
}
}
Код: Выделить всё
@Composable
fun MovieList(movies: List, onClick: (Int) -> Unit) {
LazyVerticalGrid(
columns = GridCells.Fixed(3),
contentPadding = PaddingValues(10.dp),
) {
itemsIndexed(
movies,
key = { _, movie -> movie.id },
) { index, movie ->
MovieItem(movie = movie, position = index, onClick = onClick)
}
}
}
Код: Выделить всё
@Composable
fun MovieScreen(
viewModel: MovieViewModel = androidx.lifecycle.viewmodel.compose.viewModel(),
) {
LaunchedEffect(Unit) {
viewModel.getMovies(getRequestModel())
}
val movieUiState by viewModel.movies.collectAsState()
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.DarkGray),
contentAlignment = Alignment.Center
) {
when (movieUiState) {
is MovieUiState.Success -> {
val movies = (movieUiState as MovieUiState.Success).movies
MovieList(movies = movies, onClick = { index ->
viewModel.changeData(index)
})
}
// Other states
}
}
}
Код: Выделить всё
@HiltViewModel
class MovieViewModel @Inject constructor(
private val movieUseCase: MovieUseCase,
) : ViewModel() {
private val _movies = MutableStateFlow(MovieUiState.Loading)
val movies = _movies.asStateFlow()
fun getMovies(request: MovieRequest) {
viewModelScope.launch {
movieUseCase.invoke(request).collect { result ->
result.onSuccess { response ->
if (response.results.isNotEmpty()) {
_movies.emit(MovieUiState.Success(response.results.toMutableStateList()))
} else {
_movies.emit(MovieUiState.Empty)
}
}.onFailure { error ->
_movies.emit(MovieUiState.Error(error.localizedMessage.orEmpty()))
}
}
}
}
fun changeData(movieIndex: Int) {
viewModelScope.launch {
val currentState = _movies.value
if (currentState is MovieUiState.Success) {
val updatedMovies = currentState.movies.apply {
this[movieIndex] = this[movieIndex].copy(posterPath = this[movieIndex].backdropPath)
}
_movies.emit(MovieUiState.Success(updatedMovies))
}
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/788 ... licking-on