When fast scrolls then lazycolumn fails to load the image and even the placeholder, tried using Coil still the issue is same with Box { Image}, SubComposeAsyncImage, AsyncImage. All three variations image fails to load from server.
@Composable
fun CharactersList(
modifier: Modifier = Modifier,
viewModel: MainActivityViewModel = hiltViewModel()
) {
val lazyPagingItems = viewModel.pagingDataFlow.collectAsLazyPagingItems()
LazyColumn(
modifier = modifier
.fillMaxSize()
.background(Color.White),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
items(
lazyPagingItems.itemCount,
key = lazyPagingItems.itemKey { it.id ?: 0 }) {
val item = lazyPagingItems[it]
if (item != null) {
CharacterListItem(item)
}
}
val loadState = lazyPagingItems.loadState
if (loadState.append is LoadState.Loading) {
item {
CircularProgressIndicator(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
)
}
}
}
}
@Composable
fun CharacterListItem(item: Result) {
Column(modifier = Modifier.background(Color.Black)) {
AsyncImage(
model = ImageRequest.Builder(
LocalContext.current)
.data(item.image)
.crossfade(true).crossfade(true)
.diskCachePolicy(CachePolicy.ENABLED)
.memoryCachePolicy(CachePolicy.ENABLED)
.build(),
contentDescription = null,
modifier = Modifier
.align(alignment = Alignment.CenterHorizontally)
.padding(top = 10.dp, bottom = 10.dp)
.size(80.dp)
.clip(CircleShape)
.aspectRatio(1f),
placeholder = painterResource(R.drawable.ic_launcher_background)
)
ManualImageLoader(item.image)
SubcomposeAsyncImage(
model = item.image,
contentDescription = null,
modifier = Modifier
.padding(vertical = 10.dp)
.size(80.dp)
.clip(CircleShape),
loading = {
// This is ALREADY centered inside the image area by Coil
Cir
Text(
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp, bottom = 10.dp),
textAlign = TextAlign.Center,
text = item.name.toString(),
fontSize = TextUnit(12f, TextUnitType.Sp),
color = Color.White
)
}
}
@Composable
fun ManualImageLoader(imageUrl: String?) {
val painter = rememberAsyncImagePainter(imageUrl)
val state = painter.state
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxWidth()) {
Image(
painter = painter,
contentDescription = null,
modifier = Modifier
.padding(top = 10.dp, bottom = 10.dp)
.size(80.dp)
.clip(CircleShape)
.aspectRatio(1f)
)
if (state is AsyncImagePainter.State.Loading) {
CircularProgressIndicator()
}
}
}
ViewModel Code:
val pagingDataFlow: Flow<PagingData<Result>> = Pager(
config = PagingConfig(pageSize = 20),
pagingSourceFactory = {
CharactersPagingSource(apiInterface)
}
).flow.cachedIn(viewModelScope)
PagingDataSource class:
class CharactersPagingSource(
private val apiInterface: ApiInterface
) : PagingSource<Int, Result>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Result> {
return try {
val nextPage = params.key ?: 1
val response = apiInterface.getPagedCharacters(page = nextPage)
LoadResult.Page(
data = response.results,
prevKey = if (nextPage == 1) null else nextPage - 1,
nextKey = if (response.results.isEmpty()) null else nextPage + 1
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
override fun getRefreshKey(state: PagingState<Int, Result>): Int? {
return state.anchorPosition?.let { anchorPos ->
state.closestPageToPosition(anchorPos)?.prevKey?.plus(1) ?: state.closestPageToPosition(
anchorPos
)?.nextKey?.minus(1)
}
}
}
As explained above I have tried all the 3 possibilities that I am aware of to make it working by AyncImage, Creating Custom ManualImageLoader, SubcomposeasyncImage. I saw some other SO threads as well where this issue persists with fast scroll where some data gets missed. Is it a common known issue with Compose or something wrong with the implementation?