Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Trying to add a reload api for Coil #1946

Closed
wants to merge 5 commits into from

Conversation

whitescent
Copy link
Contributor

@whitescent whitescent commented Dec 10, 2023

This PR is trying to fix #884 #132

I use coil in my social apps, but in some cases, pictures may fail to load. I need to tell users and let them manually try to refresh or let coil reload pictures automatically. However, coil has not provided relevant api yet. After I checked # 884, I want to decide to try to submit a PR for coil to complete this function.

But the implementation is a bit rudimentary, and I'm trying to do it mainly with your public API idea under #884 comment

Now the general way to use it is like this:

if use AsyncImage and want to retry:

val requestHandle = rememberAsyncImageRequestHandle()
Box {
  var loadState by remember { mutableStateOf<State>(Empty) }
  AsyncImage(
      model = ImageRequest.Builder(LocalContext.current)
          .data(image.uri)
          .parameters(image.parameters)
          .build(),
      requestHandle = requestHandle,
      placeholder = ColorPainter(Color(image.color)),
      error = ColorPainter(Color.Red),
      onSuccess = {
          loadState = it
          placeholder = it.result.memoryCacheKey
      },
      onError = {
          loadState = it
      },
      onLoading = {
          loadState = it
      },
      contentDescription = null,
      contentScale = ContentScale.Crop,
      modifier = Modifier
          .size(size)
          .clickable { onImageClick(image, placeholder) }
  )
  LaunchedEffect(Unit) {
      snapshotFlow { loadState }
          .distinctUntilChanged()
          .filter { it is State.Error }
          .collect {
              requestHandle.retry()
              delay(3000)
          }
  }
demo.mp4

Although this does allow coil to reload images, the implementation is not very elegant

if use AsyncImagePainter :

val painter = rememberAsyncImagePainter(
    model = ImageRequest.Builder(LocalContext.current)
        .data(image.uri)
        .parameters(image.parameters)
        .requestHandle(requestHandle)
        .build()
)
Box(contentAlignment = Alignment.Center) {
    Image(
        painter = painter,
        contentDescription = null,
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .size(size)
            .clickable { onImageClick(image, placeholder) }
    )
    when (val state = painter.state) {
        is AsyncImagePainter.State.Error -> {
            // we can manually trigger recomposition here to
            // try to reload the image
            Button(onClick = { requestHandle.retry() }) { Text("retry") }
        }
        is AsyncImagePainter.State.Success -> placeholder = state.result.memoryCacheKey
        is AsyncImagePainter.State.Loading ->
            CircularProgressIndicator(Modifier.size(36.dp), color = Color.Blue)
        else -> Unit
    }
}
demo2.mp4

Since I'm not sure if AsyncImage has become stable, it's not clear if it's a good time to implement the reload api, but maybe we can discuss more specific api design & implementation here :)

@whitescent whitescent closed this Dec 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reload image after a failed load in Jetpack Compose
1 participant